evlog 2.4.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +2 -1
  2. package/dist/{_http-DVDwNag0.mjs → _http-DHpGetLZ.mjs} +2 -6
  3. package/dist/{_http-DVDwNag0.mjs.map → _http-DHpGetLZ.mjs.map} +1 -1
  4. package/dist/{_severity-78FkT5MD.mjs → _severity-Q1BuITU_.mjs} +2 -2
  5. package/dist/{_severity-78FkT5MD.mjs.map → _severity-Q1BuITU_.mjs.map} +1 -1
  6. package/dist/adapters/axiom.d.mts +1 -1
  7. package/dist/adapters/axiom.d.mts.map +1 -1
  8. package/dist/adapters/axiom.mjs +2 -3
  9. package/dist/adapters/axiom.mjs.map +1 -1
  10. package/dist/adapters/better-stack.d.mts +1 -1
  11. package/dist/adapters/better-stack.d.mts.map +1 -1
  12. package/dist/adapters/better-stack.mjs +2 -3
  13. package/dist/adapters/better-stack.mjs.map +1 -1
  14. package/dist/adapters/otlp.d.mts +1 -1
  15. package/dist/adapters/otlp.d.mts.map +1 -1
  16. package/dist/adapters/otlp.mjs +14 -11
  17. package/dist/adapters/otlp.mjs.map +1 -1
  18. package/dist/adapters/posthog.d.mts +1 -1
  19. package/dist/adapters/posthog.d.mts.map +1 -1
  20. package/dist/adapters/posthog.mjs +2 -3
  21. package/dist/adapters/posthog.mjs.map +1 -1
  22. package/dist/adapters/sentry.d.mts +1 -1
  23. package/dist/adapters/sentry.d.mts.map +1 -1
  24. package/dist/adapters/sentry.mjs +3 -4
  25. package/dist/adapters/sentry.mjs.map +1 -1
  26. package/dist/browser.d.mts +1 -1
  27. package/dist/browser.mjs +1 -2
  28. package/dist/browser.mjs.map +1 -1
  29. package/dist/{dist-By0jiJRA.mjs → dist-BsWcv7B8.mjs} +3 -4
  30. package/dist/{dist-By0jiJRA.mjs.map → dist-BsWcv7B8.mjs.map} +1 -1
  31. package/dist/elysia/index.d.mts +2 -2
  32. package/dist/elysia/index.mjs +2 -3
  33. package/dist/elysia/index.mjs.map +1 -1
  34. package/dist/enrichers.d.mts +1 -1
  35. package/dist/enrichers.mjs +1 -1
  36. package/dist/enrichers.mjs.map +1 -1
  37. package/dist/error-iV3zJCY3.d.mts +65 -0
  38. package/dist/error-iV3zJCY3.d.mts.map +1 -0
  39. package/dist/error.d.mts +2 -65
  40. package/dist/error.mjs +1 -2
  41. package/dist/error.mjs.map +1 -1
  42. package/dist/errors-BJRXUfMg.mjs +18 -0
  43. package/dist/errors-BJRXUfMg.mjs.map +1 -0
  44. package/dist/errors-CKSfdvLa.d.mts +39 -0
  45. package/dist/errors-CKSfdvLa.d.mts.map +1 -0
  46. package/dist/express/index.d.mts +2 -2
  47. package/dist/express/index.mjs +3 -4
  48. package/dist/express/index.mjs.map +1 -1
  49. package/dist/fastify/index.d.mts +2 -2
  50. package/dist/fastify/index.d.mts.map +1 -1
  51. package/dist/fastify/index.mjs +3 -4
  52. package/dist/fastify/index.mjs.map +1 -1
  53. package/dist/{headers-CXOd5EyZ.mjs → headers-Ba1eKT3i.mjs} +6 -6
  54. package/dist/headers-Ba1eKT3i.mjs.map +1 -0
  55. package/dist/hono/index.d.mts +2 -2
  56. package/dist/hono/index.mjs +2 -3
  57. package/dist/hono/index.mjs.map +1 -1
  58. package/dist/index.d.mts +5 -5
  59. package/dist/index.mjs +1 -2
  60. package/dist/logger-CvDYZUze.d.mts +59 -0
  61. package/dist/logger-CvDYZUze.d.mts.map +1 -0
  62. package/dist/logger.d.mts +2 -59
  63. package/dist/logger.mjs +45 -3
  64. package/dist/logger.mjs.map +1 -1
  65. package/dist/middleware-hZqyXoSk.d.mts +75 -0
  66. package/dist/middleware-hZqyXoSk.d.mts.map +1 -0
  67. package/dist/nestjs/index.d.mts +2 -2
  68. package/dist/nestjs/index.mjs +3 -4
  69. package/dist/nestjs/index.mjs.map +1 -1
  70. package/dist/next/client.d.mts +1 -1
  71. package/dist/next/client.mjs +2 -4
  72. package/dist/next/client.mjs.map +1 -1
  73. package/dist/next/index.d.mts +4 -4
  74. package/dist/next/index.d.mts.map +1 -1
  75. package/dist/next/index.mjs +2 -6
  76. package/dist/next/index.mjs.map +1 -1
  77. package/dist/nitro/errorHandler.mjs +3 -3
  78. package/dist/nitro/errorHandler.mjs.map +1 -1
  79. package/dist/nitro/module.d.mts +2 -2
  80. package/dist/nitro/module.mjs +1 -2
  81. package/dist/nitro/module.mjs.map +1 -1
  82. package/dist/nitro/plugin.mjs +3 -4
  83. package/dist/nitro/plugin.mjs.map +1 -1
  84. package/dist/nitro/v3/errorHandler.mjs +4 -4
  85. package/dist/nitro/v3/errorHandler.mjs.map +1 -1
  86. package/dist/nitro/v3/index.mjs +1 -2
  87. package/dist/nitro/v3/middleware.mjs +1 -2
  88. package/dist/nitro/v3/middleware.mjs.map +1 -1
  89. package/dist/nitro/v3/module.d.mts +1 -1
  90. package/dist/nitro/v3/module.mjs +4 -3
  91. package/dist/nitro/v3/module.mjs.map +1 -1
  92. package/dist/nitro/v3/plugin.d.mts +3 -1
  93. package/dist/nitro/v3/plugin.mjs +4 -5
  94. package/dist/nitro/v3/plugin.mjs.map +1 -1
  95. package/dist/nitro/v3/useLogger.d.mts +1 -1
  96. package/dist/nitro/v3/useLogger.mjs +1 -1
  97. package/dist/nitro/v3/useLogger.mjs.map +1 -1
  98. package/dist/{nitro-BRisWfGy.d.mts → nitro-CGGTUned.d.mts} +2 -2
  99. package/dist/nitro-CGGTUned.d.mts.map +1 -0
  100. package/dist/{nitro-Da8tEfJ3.mjs → nitro-D1pPm37T.mjs} +4 -9
  101. package/dist/nitro-D1pPm37T.mjs.map +1 -0
  102. package/dist/nuxt/module.d.mts +1 -1
  103. package/dist/nuxt/module.mjs +2 -5
  104. package/dist/nuxt/module.mjs.map +1 -1
  105. package/dist/parseError-BztqcPwZ.d.mts +7 -0
  106. package/dist/parseError-BztqcPwZ.d.mts.map +1 -0
  107. package/dist/pipeline.mjs +1 -1
  108. package/dist/{routes-BNbrnm14.mjs → routes-CE3_c-iZ.mjs} +2 -3
  109. package/dist/{routes-BNbrnm14.mjs.map → routes-CE3_c-iZ.mjs.map} +1 -1
  110. package/dist/runtime/client/log.d.mts +1 -1
  111. package/dist/runtime/client/log.d.mts.map +1 -1
  112. package/dist/runtime/client/log.mjs +4 -11
  113. package/dist/runtime/client/log.mjs.map +1 -1
  114. package/dist/runtime/client/plugin.mjs +1 -2
  115. package/dist/runtime/client/plugin.mjs.map +1 -1
  116. package/dist/runtime/server/routes/_evlog/ingest.post.mjs +1 -2
  117. package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
  118. package/dist/runtime/server/useLogger.d.mts +2 -39
  119. package/dist/runtime/server/useLogger.mjs +1 -1
  120. package/dist/runtime/server/useLogger.mjs.map +1 -1
  121. package/dist/runtime/utils/parseError.d.mts +3 -7
  122. package/dist/runtime/utils/parseError.mjs +1 -1
  123. package/dist/{storage-CejtuV76.mjs → storage-CJBW5Vos.mjs} +4 -3
  124. package/dist/storage-CJBW5Vos.mjs.map +1 -0
  125. package/dist/sveltekit/index.d.mts +2 -2
  126. package/dist/sveltekit/index.mjs +5 -5
  127. package/dist/toolkit.d.mts +38 -0
  128. package/dist/toolkit.d.mts.map +1 -0
  129. package/dist/toolkit.mjs +5 -0
  130. package/dist/types-B8-kC2ME.d.mts +496 -0
  131. package/dist/types-B8-kC2ME.d.mts.map +1 -0
  132. package/dist/types.d.mts +2 -496
  133. package/dist/types.mjs +1 -1
  134. package/dist/useLogger-_Ec6mXoR.d.mts +39 -0
  135. package/dist/useLogger-_Ec6mXoR.d.mts.map +1 -0
  136. package/dist/utils.d.mts +18 -2
  137. package/dist/utils.d.mts.map +1 -1
  138. package/dist/utils.mjs +28 -2
  139. package/dist/utils.mjs.map +1 -1
  140. package/dist/workers.d.mts +1 -1
  141. package/dist/workers.mjs +1 -2
  142. package/dist/workers.mjs.map +1 -1
  143. package/package.json +68 -39
  144. package/dist/error.d.mts.map +0 -1
  145. package/dist/headers-CXOd5EyZ.mjs.map +0 -1
  146. package/dist/logger.d.mts.map +0 -1
  147. package/dist/middleware-BoVCgsfQ.d.mts +0 -36
  148. package/dist/middleware-BoVCgsfQ.d.mts.map +0 -1
  149. package/dist/nitro-BRisWfGy.d.mts.map +0 -1
  150. package/dist/nitro-Da8tEfJ3.mjs.map +0 -1
  151. package/dist/runtime/server/useLogger.d.mts.map +0 -1
  152. package/dist/runtime/utils/parseError.d.mts.map +0 -1
  153. package/dist/storage-CejtuV76.mjs.map +0 -1
  154. package/dist/types.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"dist-By0jiJRA.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":";AAQA,MAAM,IAAI,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-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,5 +1,5 @@
1
- import { RequestLogger } from "../types.mjs";
2
- import { t as BaseEvlogOptions } from "../middleware-BoVCgsfQ.mjs";
1
+ import { g as RequestLogger } from "../types-B8-kC2ME.mjs";
2
+ import { t as BaseEvlogOptions } from "../middleware-hZqyXoSk.mjs";
3
3
  import { Elysia } from "elysia";
4
4
 
5
5
  //#region src/elysia/index.d.ts
@@ -1,7 +1,6 @@
1
- import { r as createMiddlewareLogger, t as extractSafeHeaders } from "../headers-CXOd5EyZ.mjs";
1
+ import { r as createMiddlewareLogger, t as extractSafeHeaders } from "../headers-Ba1eKT3i.mjs";
2
2
  import { AsyncLocalStorage } from "node:async_hooks";
3
3
  import { Elysia } from "elysia";
4
-
5
4
  //#region src/elysia/index.ts
6
5
  const storage = new AsyncLocalStorage();
7
6
  const activeLoggers = /* @__PURE__ */ new WeakSet();
@@ -66,7 +65,7 @@ function evlog(options = {}) {
66
65
  storage.enterWith(void 0);
67
66
  });
68
67
  }
69
-
70
68
  //#endregion
71
69
  export { evlog, useLogger };
70
+
72
71
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/elysia/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { Elysia } from 'elysia'\nimport type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { extractSafeHeaders } from '../shared/headers'\n\nconst storage = new AsyncLocalStorage<RequestLogger>()\n\n// Tracks loggers that are currently active (within a live request).\n// Elysia uses storage.enterWith() which persists in the async context\n// even after the request ends, so we use this set to distinguish\n// an in-flight logger from a stale one.\nconst activeLoggers = new WeakSet<RequestLogger>()\n\nexport type EvlogElysiaOptions = BaseEvlogOptions\n\n/**\n * Get the request-scoped logger from anywhere in the call stack.\n * Must be called inside a request handled by the `evlog()` plugin.\n *\n * Unlike other frameworks, Elysia uses `storage.enterWith()` which persists\n * beyond the request lifecycle. This accessor additionally checks `activeLoggers`\n * to ensure the logger belongs to an in-flight request.\n *\n * @example\n * ```ts\n * import { useLogger } from 'evlog/elysia'\n *\n * function findUser(id: string) {\n * const log = useLogger()\n * log.set({ user: { id } })\n * }\n * ```\n */\nexport function useLogger<T extends object = Record<string, unknown>>(): RequestLogger<T> {\n const logger = storage.getStore()\n if (!logger || !activeLoggers.has(logger)) {\n throw new Error(\n '[evlog] useLogger() was called outside of an evlog plugin context. '\n + 'Make sure app.use(evlog()) is registered before your routes.',\n )\n }\n return logger as RequestLogger<T>\n}\n\n/**\n * Create an evlog plugin for Elysia.\n *\n * @example\n * ```ts\n * import { Elysia } from 'elysia'\n * import { evlog } from 'evlog/elysia'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * const app = new Elysia()\n * .use(evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * }))\n * .get('/health', ({ log }) => {\n * log.set({ route: 'health' })\n * return { ok: true }\n * })\n * .listen(3000)\n * ```\n */\ninterface RequestState {\n finish: (opts?: { status?: number; error?: Error }) => Promise<unknown>\n skipped: boolean\n logger: RequestLogger\n}\n\nexport function evlog(options: EvlogElysiaOptions = {}) {\n const emitted = new WeakSet<Request>()\n const requestState = new WeakMap<Request, RequestState>()\n\n return new Elysia({ name: 'evlog' })\n .derive({ as: 'global' }, ({ request }) => {\n const url = new URL(request.url)\n\n const { logger, finish, skipped } = createMiddlewareLogger({\n method: request.method,\n path: url.pathname,\n requestId: request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(request.headers),\n ...options,\n })\n\n if (!skipped) activeLoggers.add(logger)\n storage.enterWith(logger)\n requestState.set(request, { finish, skipped, logger })\n\n return { log: logger }\n })\n .onAfterHandle({ as: 'global' }, async ({ request, set }) => {\n const state = requestState.get(request)\n if (!state || state.skipped || emitted.has(request)) return\n emitted.add(request)\n await state.finish({ status: set.status as number || 200 })\n activeLoggers.delete(state.logger)\n storage.enterWith(undefined as unknown as RequestLogger)\n })\n .onError({ as: 'global' }, async ({ request, error }) => {\n const state = requestState.get(request)\n if (!state || state.skipped || emitted.has(request)) return\n emitted.add(request)\n const err = error instanceof Error ? error : new Error(String(error))\n state.logger.error(err)\n await state.finish({ error: err })\n activeLoggers.delete(state.logger)\n storage.enterWith(undefined as unknown as RequestLogger)\n })\n}\n"],"mappings":";;;;;AAMA,MAAM,UAAU,IAAI,mBAAkC;AAMtD,MAAM,gCAAgB,IAAI,SAAwB;;;;;;;;;;;;;;;;;;;AAsBlD,SAAgB,YAA0E;CACxF,MAAM,SAAS,QAAQ,UAAU;AACjC,KAAI,CAAC,UAAU,CAAC,cAAc,IAAI,OAAO,CACvC,OAAM,IAAI,MACR,kIAED;AAEH,QAAO;;AAgCT,SAAgB,MAAM,UAA8B,EAAE,EAAE;CACtD,MAAM,0BAAU,IAAI,SAAkB;CACtC,MAAM,+BAAe,IAAI,SAAgC;AAEzD,QAAO,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC,CACjC,OAAO,EAAE,IAAI,UAAU,GAAG,EAAE,cAAc;EACzC,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;EAEhC,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,QAAQ;GAChB,MAAM,IAAI;GACV,WAAW,QAAQ,QAAQ,IAAI,eAAe,IAAI,OAAO,YAAY;GACrE,SAAS,mBAAmB,QAAQ,QAAQ;GAC5C,GAAG;GACJ,CAAC;AAEF,MAAI,CAAC,QAAS,eAAc,IAAI,OAAO;AACvC,UAAQ,UAAU,OAAO;AACzB,eAAa,IAAI,SAAS;GAAE;GAAQ;GAAS;GAAQ,CAAC;AAEtD,SAAO,EAAE,KAAK,QAAQ;GACtB,CACD,cAAc,EAAE,IAAI,UAAU,EAAE,OAAO,EAAE,SAAS,UAAU;EAC3D,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,MAAM,WAAW,QAAQ,IAAI,QAAQ,CAAE;AACrD,UAAQ,IAAI,QAAQ;AACpB,QAAM,MAAM,OAAO,EAAE,QAAQ,IAAI,UAAoB,KAAK,CAAC;AAC3D,gBAAc,OAAO,MAAM,OAAO;AAClC,UAAQ,UAAU,OAAsC;GACxD,CACD,QAAQ,EAAE,IAAI,UAAU,EAAE,OAAO,EAAE,SAAS,YAAY;EACvD,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,MAAM,WAAW,QAAQ,IAAI,QAAQ,CAAE;AACrD,UAAQ,IAAI,QAAQ;EACpB,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AACrE,QAAM,OAAO,MAAM,IAAI;AACvB,QAAM,MAAM,OAAO,EAAE,OAAO,KAAK,CAAC;AAClC,gBAAc,OAAO,MAAM,OAAO;AAClC,UAAQ,UAAU,OAAsC;GACxD"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/elysia/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { Elysia } from 'elysia'\nimport type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { extractSafeHeaders } from '../shared/headers'\n\nconst storage = new AsyncLocalStorage<RequestLogger>()\n\n// Tracks loggers that are currently active (within a live request).\n// Elysia uses storage.enterWith() which persists in the async context\n// even after the request ends, so we use this set to distinguish\n// an in-flight logger from a stale one.\nconst activeLoggers = new WeakSet<RequestLogger>()\n\nexport type EvlogElysiaOptions = BaseEvlogOptions\n\n/**\n * Get the request-scoped logger from anywhere in the call stack.\n * Must be called inside a request handled by the `evlog()` plugin.\n *\n * Unlike other frameworks, Elysia uses `storage.enterWith()` which persists\n * beyond the request lifecycle. This accessor additionally checks `activeLoggers`\n * to ensure the logger belongs to an in-flight request.\n *\n * @example\n * ```ts\n * import { useLogger } from 'evlog/elysia'\n *\n * function findUser(id: string) {\n * const log = useLogger()\n * log.set({ user: { id } })\n * }\n * ```\n */\nexport function useLogger<T extends object = Record<string, unknown>>(): RequestLogger<T> {\n const logger = storage.getStore()\n if (!logger || !activeLoggers.has(logger)) {\n throw new Error(\n '[evlog] useLogger() was called outside of an evlog plugin context. '\n + 'Make sure app.use(evlog()) is registered before your routes.',\n )\n }\n return logger as RequestLogger<T>\n}\n\n/**\n * Create an evlog plugin for Elysia.\n *\n * @example\n * ```ts\n * import { Elysia } from 'elysia'\n * import { evlog } from 'evlog/elysia'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * const app = new Elysia()\n * .use(evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * }))\n * .get('/health', ({ log }) => {\n * log.set({ route: 'health' })\n * return { ok: true }\n * })\n * .listen(3000)\n * ```\n */\ninterface RequestState {\n finish: (opts?: { status?: number; error?: Error }) => Promise<unknown>\n skipped: boolean\n logger: RequestLogger\n}\n\nexport function evlog(options: EvlogElysiaOptions = {}) {\n const emitted = new WeakSet<Request>()\n const requestState = new WeakMap<Request, RequestState>()\n\n return new Elysia({ name: 'evlog' })\n .derive({ as: 'global' }, ({ request }) => {\n const url = new URL(request.url)\n\n const { logger, finish, skipped } = createMiddlewareLogger({\n method: request.method,\n path: url.pathname,\n requestId: request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(request.headers),\n ...options,\n })\n\n if (!skipped) activeLoggers.add(logger)\n storage.enterWith(logger)\n requestState.set(request, { finish, skipped, logger })\n\n return { log: logger }\n })\n .onAfterHandle({ as: 'global' }, async ({ request, set }) => {\n const state = requestState.get(request)\n if (!state || state.skipped || emitted.has(request)) return\n emitted.add(request)\n await state.finish({ status: set.status as number || 200 })\n activeLoggers.delete(state.logger)\n storage.enterWith(undefined as unknown as RequestLogger)\n })\n .onError({ as: 'global' }, async ({ request, error }) => {\n const state = requestState.get(request)\n if (!state || state.skipped || emitted.has(request)) return\n emitted.add(request)\n const err = error instanceof Error ? error : new Error(String(error))\n state.logger.error(err)\n await state.finish({ error: err })\n activeLoggers.delete(state.logger)\n storage.enterWith(undefined as unknown as RequestLogger)\n })\n}\n"],"mappings":";;;;AAMA,MAAM,UAAU,IAAI,mBAAkC;AAMtD,MAAM,gCAAgB,IAAI,SAAwB;;;;;;;;;;;;;;;;;;;AAsBlD,SAAgB,YAA0E;CACxF,MAAM,SAAS,QAAQ,UAAU;AACjC,KAAI,CAAC,UAAU,CAAC,cAAc,IAAI,OAAO,CACvC,OAAM,IAAI,MACR,kIAED;AAEH,QAAO;;AAgCT,SAAgB,MAAM,UAA8B,EAAE,EAAE;CACtD,MAAM,0BAAU,IAAI,SAAkB;CACtC,MAAM,+BAAe,IAAI,SAAgC;AAEzD,QAAO,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC,CACjC,OAAO,EAAE,IAAI,UAAU,GAAG,EAAE,cAAc;EACzC,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;EAEhC,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,QAAQ;GAChB,MAAM,IAAI;GACV,WAAW,QAAQ,QAAQ,IAAI,eAAe,IAAI,OAAO,YAAY;GACrE,SAAS,mBAAmB,QAAQ,QAAQ;GAC5C,GAAG;GACJ,CAAC;AAEF,MAAI,CAAC,QAAS,eAAc,IAAI,OAAO;AACvC,UAAQ,UAAU,OAAO;AACzB,eAAa,IAAI,SAAS;GAAE;GAAQ;GAAS;GAAQ,CAAC;AAEtD,SAAO,EAAE,KAAK,QAAQ;GACtB,CACD,cAAc,EAAE,IAAI,UAAU,EAAE,OAAO,EAAE,SAAS,UAAU;EAC3D,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,MAAM,WAAW,QAAQ,IAAI,QAAQ,CAAE;AACrD,UAAQ,IAAI,QAAQ;AACpB,QAAM,MAAM,OAAO,EAAE,QAAQ,IAAI,UAAoB,KAAK,CAAC;AAC3D,gBAAc,OAAO,MAAM,OAAO;AAClC,UAAQ,UAAU,KAAA,EAAsC;GACxD,CACD,QAAQ,EAAE,IAAI,UAAU,EAAE,OAAO,EAAE,SAAS,YAAY;EACvD,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,MAAM,WAAW,QAAQ,IAAI,QAAQ,CAAE;AACrD,UAAQ,IAAI,QAAQ;EACpB,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AACrE,QAAM,OAAO,MAAM,IAAI;AACvB,QAAM,MAAM,OAAO,EAAE,OAAO,KAAK,CAAC;AAClC,gBAAc,OAAO,MAAM,OAAO;AAClC,UAAQ,UAAU,KAAA,EAAsC;GACxD"}
@@ -1,4 +1,4 @@
1
- import { EnrichContext } from "./types.mjs";
1
+ import { i as EnrichContext } from "./types-B8-kC2ME.mjs";
2
2
 
3
3
  //#region src/enrichers/index.d.ts
4
4
  interface EnricherOptions {
@@ -166,7 +166,7 @@ function createTraceContextEnricher(options = {}) {
166
166
  if (mergedTraceContext.spanId && (options.overwrite || ctx.event.spanId === void 0)) ctx.event.spanId = mergedTraceContext.spanId;
167
167
  };
168
168
  }
169
-
170
169
  //#endregion
171
170
  export { createGeoEnricher, createRequestSizeEnricher, createTraceContextEnricher, createUserAgentEnricher };
171
+
172
172
  //# sourceMappingURL=enrichers.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"enrichers.mjs","names":[],"sources":["../src/enrichers/index.ts"],"sourcesContent":["import type { EnrichContext } from '../types'\n\nexport interface EnricherOptions {\n /**\n * When true, overwrite any existing fields in the event.\n * Defaults to false to preserve user-provided data.\n */\n overwrite?: boolean\n}\n\nexport interface UserAgentInfo {\n raw: string\n browser?: { name: string; version?: string }\n os?: { name: string; version?: string }\n device?: { type: 'mobile' | 'tablet' | 'desktop' | 'bot' | 'unknown' }\n}\n\nexport interface GeoInfo {\n country?: string\n region?: string\n regionCode?: string\n city?: string\n latitude?: number\n longitude?: number\n}\n\nexport interface RequestSizeInfo {\n requestBytes?: number\n responseBytes?: number\n}\n\nexport interface TraceContextInfo {\n traceparent?: string\n tracestate?: string\n traceId?: string\n spanId?: string\n}\n\nfunction getHeader(headers: Record<string, string> | undefined, name: string): string | undefined {\n if (!headers) return undefined\n if (headers[name] !== undefined) return headers[name]\n const lowerName = name.toLowerCase()\n if (headers[lowerName] !== undefined) return headers[lowerName]\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lowerName) return value\n }\n return undefined\n}\n\nfunction parseUserAgent(ua: string): UserAgentInfo {\n const lower = ua.toLowerCase()\n\n let deviceType: UserAgentInfo['device'] = { type: 'unknown' }\n if (/bot|crawl|spider|slurp|bingpreview/.test(lower)) {\n deviceType = { type: 'bot' }\n } else if (/ipad|tablet/.test(lower)) {\n deviceType = { type: 'tablet' }\n } else if (/mobi|iphone|android/.test(lower)) {\n deviceType = { type: 'mobile' }\n } else if (ua.length > 0) {\n deviceType = { type: 'desktop' }\n }\n\n const browserMatchers: Array<{ name: string, regex: RegExp }> = [\n { name: 'Edge', regex: /edg\\/([\\d.]+)/i },\n { name: 'Chrome', regex: /chrome\\/([\\d.]+)/i },\n { name: 'Firefox', regex: /firefox\\/([\\d.]+)/i },\n { name: 'Safari', regex: /version\\/([\\d.]+).*safari/i },\n ]\n\n let browser: UserAgentInfo['browser']\n for (const matcher of browserMatchers) {\n const match = ua.match(matcher.regex)\n if (match) {\n browser = { name: matcher.name, version: match[1] }\n break\n }\n }\n\n let os: UserAgentInfo['os']\n if (/windows nt/i.test(ua)) {\n const match = ua.match(/windows nt ([\\d.]+)/i)\n os = { name: 'Windows', version: match?.[1] }\n } else if (/mac os x/i.test(ua) && !/iphone|ipad|ipod/i.test(ua)) {\n const match = ua.match(/mac os x ([\\d_]+)/i)\n os = { name: 'macOS', version: match?.[1]?.replace(/_/g, '.') }\n } else if (/iphone|ipad|ipod/i.test(ua)) {\n const match = ua.match(/os ([\\d_]+)/i)\n os = { name: 'iOS', version: match?.[1]?.replace(/_/g, '.') }\n } else if (/android/i.test(ua)) {\n const match = ua.match(/android ([\\d.]+)/i)\n os = { name: 'Android', version: match?.[1] }\n } else if (/linux/i.test(ua)) {\n os = { name: 'Linux' }\n }\n\n return {\n raw: ua,\n browser,\n os,\n device: deviceType,\n }\n}\n\nfunction parseTraceparent(traceparent: string): Pick<TraceContextInfo, 'traceId' | 'spanId'> | undefined {\n const match = traceparent.match(/^[\\da-f]{2}-([\\da-f]{32})-([\\da-f]{16})-[\\da-f]{2}$/i)\n if (!match) return undefined\n return { traceId: match[1], spanId: match[2] }\n}\n\nfunction mergeEventField<T extends object>(\n existing: unknown,\n computed: T,\n overwrite?: boolean,\n): T {\n if (overwrite || existing === undefined || existing === null || typeof existing !== 'object') {\n return computed\n }\n return { ...computed, ...(existing as T) }\n}\n\nfunction normalizeNumber(value: string | undefined): number | undefined {\n if (!value) return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\n/**\n * Enrich events with parsed user agent data.\n * Sets `event.userAgent` with `UserAgentInfo` shape: `{ raw, browser?, os?, device? }`.\n */\nexport function createUserAgentEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const ua = getHeader(ctx.headers, 'user-agent')\n if (!ua) return\n const info = parseUserAgent(ua)\n ctx.event.userAgent = mergeEventField<UserAgentInfo>(ctx.event.userAgent, info, options.overwrite)\n }\n}\n\n/**\n * Enrich events with geo data from platform headers.\n * Sets `event.geo` with `GeoInfo` shape: `{ country?, region?, regionCode?, city?, latitude?, longitude? }`.\n *\n * Supports Vercel (`x-vercel-ip-*`) headers out of the box.\n *\n * **Cloudflare note:** Only `cf-ipcountry` is an actual HTTP header added by Cloudflare.\n * The `cf-region`, `cf-city`, `cf-latitude`, `cf-longitude` headers are NOT standard\n * Cloudflare headers — they are properties of `request.cf` which is not exposed as HTTP\n * headers. For full geo data on Cloudflare, write a custom enricher that reads `request.cf`\n * or use a Workers middleware to copy `cf` properties into custom headers.\n */\nexport function createGeoEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const { headers } = ctx\n if (!headers) return\n\n const geo: GeoInfo = {\n country: getHeader(headers, 'x-vercel-ip-country') ?? getHeader(headers, 'cf-ipcountry'),\n region: getHeader(headers, 'x-vercel-ip-country-region') ?? getHeader(headers, 'cf-region'),\n regionCode: getHeader(headers, 'x-vercel-ip-country-region-code') ?? getHeader(headers, 'cf-region-code'),\n city: getHeader(headers, 'x-vercel-ip-city') ?? getHeader(headers, 'cf-city'),\n latitude: normalizeNumber(getHeader(headers, 'x-vercel-ip-latitude') ?? getHeader(headers, 'cf-latitude')),\n longitude: normalizeNumber(getHeader(headers, 'x-vercel-ip-longitude') ?? getHeader(headers, 'cf-longitude')),\n }\n\n if (Object.values(geo).every(value => value === undefined)) return\n ctx.event.geo = mergeEventField<GeoInfo>(ctx.event.geo, geo, options.overwrite)\n }\n}\n\n/**\n * Enrich events with request/response payload sizes.\n * Sets `event.requestSize` with `RequestSizeInfo` shape: `{ requestBytes?, responseBytes? }`.\n */\nexport function createRequestSizeEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const requestBytes = normalizeNumber(getHeader(ctx.headers, 'content-length'))\n const responseBytes = normalizeNumber(getHeader(ctx.response?.headers, 'content-length'))\n\n const sizes: RequestSizeInfo = {\n requestBytes,\n responseBytes,\n }\n\n if (requestBytes === undefined && responseBytes === undefined) return\n ctx.event.requestSize = mergeEventField<RequestSizeInfo>(ctx.event.requestSize, sizes, options.overwrite)\n }\n}\n\n/**\n * Enrich events with W3C trace context data.\n * Sets `event.traceContext` with `TraceContextInfo` shape: `{ traceparent?, tracestate?, traceId?, spanId? }`.\n * Also sets `event.traceId` and `event.spanId` at the top level.\n */\nexport function createTraceContextEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const traceparent = getHeader(ctx.headers, 'traceparent')\n const tracestate = getHeader(ctx.headers, 'tracestate')\n if (!traceparent && !tracestate) return\n\n const parsed = traceparent ? parseTraceparent(traceparent) : undefined\n const incomingTraceContext: TraceContextInfo = {\n traceparent,\n tracestate,\n traceId: parsed?.traceId ?? (ctx.event.traceId as string | undefined),\n spanId: parsed?.spanId ?? (ctx.event.spanId as string | undefined),\n }\n\n const mergedTraceContext = mergeEventField<TraceContextInfo>(\n ctx.event.traceContext,\n incomingTraceContext,\n options.overwrite,\n )\n ctx.event.traceContext = mergedTraceContext\n\n if (mergedTraceContext.traceId && (options.overwrite || ctx.event.traceId === undefined)) {\n ctx.event.traceId = mergedTraceContext.traceId\n }\n if (mergedTraceContext.spanId && (options.overwrite || ctx.event.spanId === undefined)) {\n ctx.event.spanId = mergedTraceContext.spanId\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"enrichers.mjs","names":[],"sources":["../src/enrichers/index.ts"],"sourcesContent":["import type { EnrichContext } from '../types'\n\nexport interface EnricherOptions {\n /**\n * When true, overwrite any existing fields in the event.\n * Defaults to false to preserve user-provided data.\n */\n overwrite?: boolean\n}\n\nexport interface UserAgentInfo {\n raw: string\n browser?: { name: string; version?: string }\n os?: { name: string; version?: string }\n device?: { type: 'mobile' | 'tablet' | 'desktop' | 'bot' | 'unknown' }\n}\n\nexport interface GeoInfo {\n country?: string\n region?: string\n regionCode?: string\n city?: string\n latitude?: number\n longitude?: number\n}\n\nexport interface RequestSizeInfo {\n requestBytes?: number\n responseBytes?: number\n}\n\nexport interface TraceContextInfo {\n traceparent?: string\n tracestate?: string\n traceId?: string\n spanId?: string\n}\n\nfunction getHeader(headers: Record<string, string> | undefined, name: string): string | undefined {\n if (!headers) return undefined\n if (headers[name] !== undefined) return headers[name]\n const lowerName = name.toLowerCase()\n if (headers[lowerName] !== undefined) return headers[lowerName]\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lowerName) return value\n }\n return undefined\n}\n\nfunction parseUserAgent(ua: string): UserAgentInfo {\n const lower = ua.toLowerCase()\n\n let deviceType: UserAgentInfo['device'] = { type: 'unknown' }\n if (/bot|crawl|spider|slurp|bingpreview/.test(lower)) {\n deviceType = { type: 'bot' }\n } else if (/ipad|tablet/.test(lower)) {\n deviceType = { type: 'tablet' }\n } else if (/mobi|iphone|android/.test(lower)) {\n deviceType = { type: 'mobile' }\n } else if (ua.length > 0) {\n deviceType = { type: 'desktop' }\n }\n\n const browserMatchers: Array<{ name: string, regex: RegExp }> = [\n { name: 'Edge', regex: /edg\\/([\\d.]+)/i },\n { name: 'Chrome', regex: /chrome\\/([\\d.]+)/i },\n { name: 'Firefox', regex: /firefox\\/([\\d.]+)/i },\n { name: 'Safari', regex: /version\\/([\\d.]+).*safari/i },\n ]\n\n let browser: UserAgentInfo['browser']\n for (const matcher of browserMatchers) {\n const match = ua.match(matcher.regex)\n if (match) {\n browser = { name: matcher.name, version: match[1] }\n break\n }\n }\n\n let os: UserAgentInfo['os']\n if (/windows nt/i.test(ua)) {\n const match = ua.match(/windows nt ([\\d.]+)/i)\n os = { name: 'Windows', version: match?.[1] }\n } else if (/mac os x/i.test(ua) && !/iphone|ipad|ipod/i.test(ua)) {\n const match = ua.match(/mac os x ([\\d_]+)/i)\n os = { name: 'macOS', version: match?.[1]?.replace(/_/g, '.') }\n } else if (/iphone|ipad|ipod/i.test(ua)) {\n const match = ua.match(/os ([\\d_]+)/i)\n os = { name: 'iOS', version: match?.[1]?.replace(/_/g, '.') }\n } else if (/android/i.test(ua)) {\n const match = ua.match(/android ([\\d.]+)/i)\n os = { name: 'Android', version: match?.[1] }\n } else if (/linux/i.test(ua)) {\n os = { name: 'Linux' }\n }\n\n return {\n raw: ua,\n browser,\n os,\n device: deviceType,\n }\n}\n\nfunction parseTraceparent(traceparent: string): Pick<TraceContextInfo, 'traceId' | 'spanId'> | undefined {\n const match = traceparent.match(/^[\\da-f]{2}-([\\da-f]{32})-([\\da-f]{16})-[\\da-f]{2}$/i)\n if (!match) return undefined\n return { traceId: match[1], spanId: match[2] }\n}\n\nfunction mergeEventField<T extends object>(\n existing: unknown,\n computed: T,\n overwrite?: boolean,\n): T {\n if (overwrite || existing === undefined || existing === null || typeof existing !== 'object') {\n return computed\n }\n return { ...computed, ...(existing as T) }\n}\n\nfunction normalizeNumber(value: string | undefined): number | undefined {\n if (!value) return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\n/**\n * Enrich events with parsed user agent data.\n * Sets `event.userAgent` with `UserAgentInfo` shape: `{ raw, browser?, os?, device? }`.\n */\nexport function createUserAgentEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const ua = getHeader(ctx.headers, 'user-agent')\n if (!ua) return\n const info = parseUserAgent(ua)\n ctx.event.userAgent = mergeEventField<UserAgentInfo>(ctx.event.userAgent, info, options.overwrite)\n }\n}\n\n/**\n * Enrich events with geo data from platform headers.\n * Sets `event.geo` with `GeoInfo` shape: `{ country?, region?, regionCode?, city?, latitude?, longitude? }`.\n *\n * Supports Vercel (`x-vercel-ip-*`) headers out of the box.\n *\n * **Cloudflare note:** Only `cf-ipcountry` is an actual HTTP header added by Cloudflare.\n * The `cf-region`, `cf-city`, `cf-latitude`, `cf-longitude` headers are NOT standard\n * Cloudflare headers — they are properties of `request.cf` which is not exposed as HTTP\n * headers. For full geo data on Cloudflare, write a custom enricher that reads `request.cf`\n * or use a Workers middleware to copy `cf` properties into custom headers.\n */\nexport function createGeoEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const { headers } = ctx\n if (!headers) return\n\n const geo: GeoInfo = {\n country: getHeader(headers, 'x-vercel-ip-country') ?? getHeader(headers, 'cf-ipcountry'),\n region: getHeader(headers, 'x-vercel-ip-country-region') ?? getHeader(headers, 'cf-region'),\n regionCode: getHeader(headers, 'x-vercel-ip-country-region-code') ?? getHeader(headers, 'cf-region-code'),\n city: getHeader(headers, 'x-vercel-ip-city') ?? getHeader(headers, 'cf-city'),\n latitude: normalizeNumber(getHeader(headers, 'x-vercel-ip-latitude') ?? getHeader(headers, 'cf-latitude')),\n longitude: normalizeNumber(getHeader(headers, 'x-vercel-ip-longitude') ?? getHeader(headers, 'cf-longitude')),\n }\n\n if (Object.values(geo).every(value => value === undefined)) return\n ctx.event.geo = mergeEventField<GeoInfo>(ctx.event.geo, geo, options.overwrite)\n }\n}\n\n/**\n * Enrich events with request/response payload sizes.\n * Sets `event.requestSize` with `RequestSizeInfo` shape: `{ requestBytes?, responseBytes? }`.\n */\nexport function createRequestSizeEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const requestBytes = normalizeNumber(getHeader(ctx.headers, 'content-length'))\n const responseBytes = normalizeNumber(getHeader(ctx.response?.headers, 'content-length'))\n\n const sizes: RequestSizeInfo = {\n requestBytes,\n responseBytes,\n }\n\n if (requestBytes === undefined && responseBytes === undefined) return\n ctx.event.requestSize = mergeEventField<RequestSizeInfo>(ctx.event.requestSize, sizes, options.overwrite)\n }\n}\n\n/**\n * Enrich events with W3C trace context data.\n * Sets `event.traceContext` with `TraceContextInfo` shape: `{ traceparent?, tracestate?, traceId?, spanId? }`.\n * Also sets `event.traceId` and `event.spanId` at the top level.\n */\nexport function createTraceContextEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const traceparent = getHeader(ctx.headers, 'traceparent')\n const tracestate = getHeader(ctx.headers, 'tracestate')\n if (!traceparent && !tracestate) return\n\n const parsed = traceparent ? parseTraceparent(traceparent) : undefined\n const incomingTraceContext: TraceContextInfo = {\n traceparent,\n tracestate,\n traceId: parsed?.traceId ?? (ctx.event.traceId as string | undefined),\n spanId: parsed?.spanId ?? (ctx.event.spanId as string | undefined),\n }\n\n const mergedTraceContext = mergeEventField<TraceContextInfo>(\n ctx.event.traceContext,\n incomingTraceContext,\n options.overwrite,\n )\n ctx.event.traceContext = mergedTraceContext\n\n if (mergedTraceContext.traceId && (options.overwrite || ctx.event.traceId === undefined)) {\n ctx.event.traceId = mergedTraceContext.traceId\n }\n if (mergedTraceContext.spanId && (options.overwrite || ctx.event.spanId === undefined)) {\n ctx.event.spanId = mergedTraceContext.spanId\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { o as ErrorOptions } from "./types-B8-kC2ME.mjs";
2
+
3
+ //#region src/error.d.ts
4
+ /**
5
+ * Structured error with context for better debugging
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * throw new EvlogError({
10
+ * message: 'Failed to sync repository',
11
+ * status: 503,
12
+ * why: 'GitHub API rate limit exceeded',
13
+ * fix: 'Wait 1 hour or use a different token',
14
+ * link: 'https://docs.github.com/en/rest/rate-limit',
15
+ * cause: originalError,
16
+ * })
17
+ * ```
18
+ */
19
+ declare class EvlogError extends Error {
20
+ /** HTTP status code */
21
+ readonly status: number;
22
+ readonly why?: string;
23
+ readonly fix?: string;
24
+ readonly link?: string;
25
+ constructor(options: ErrorOptions | string);
26
+ /** HTTP status text (alias for message) */
27
+ get statusText(): string;
28
+ /** HTTP status code (alias for compatibility) */
29
+ get statusCode(): number;
30
+ /** HTTP status message (alias for compatibility) */
31
+ get statusMessage(): string;
32
+ /** Structured data for serialization */
33
+ get data(): {
34
+ why?: string;
35
+ fix?: string;
36
+ link?: string;
37
+ } | undefined;
38
+ toString(): string;
39
+ toJSON(): Record<string, unknown>;
40
+ }
41
+ /**
42
+ * Create a structured error with context for debugging and user-facing messages.
43
+ *
44
+ * @param options - Error message string or full options object
45
+ * @returns EvlogError with HTTP metadata (`status`, `statusText`) and `data`; also includes `statusCode` and `statusMessage` for legacy compatibility
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * // Simple error
50
+ * throw createError('Something went wrong')
51
+ *
52
+ * // Structured error with context
53
+ * throw createError({
54
+ * message: 'Payment failed',
55
+ * status: 402,
56
+ * why: 'Card declined by issuer',
57
+ * fix: 'Try a different payment method',
58
+ * link: 'https://docs.example.com/payments',
59
+ * })
60
+ * ```
61
+ */
62
+ declare function createError(options: ErrorOptions | string): EvlogError;
63
+ //#endregion
64
+ export { createError as n, EvlogError as t };
65
+ //# sourceMappingURL=error-iV3zJCY3.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-iV3zJCY3.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,65 +1,2 @@
1
- import { ErrorOptions } from "./types.mjs";
2
-
3
- //#region src/error.d.ts
4
- /**
5
- * Structured error with context for better debugging
6
- *
7
- * @example
8
- * ```ts
9
- * throw new EvlogError({
10
- * message: 'Failed to sync repository',
11
- * status: 503,
12
- * why: 'GitHub API rate limit exceeded',
13
- * fix: 'Wait 1 hour or use a different token',
14
- * link: 'https://docs.github.com/en/rest/rate-limit',
15
- * cause: originalError,
16
- * })
17
- * ```
18
- */
19
- declare class EvlogError extends Error {
20
- /** HTTP status code */
21
- readonly status: number;
22
- readonly why?: string;
23
- readonly fix?: string;
24
- readonly link?: string;
25
- constructor(options: ErrorOptions | string);
26
- /** HTTP status text (alias for message) */
27
- get statusText(): string;
28
- /** HTTP status code (alias for compatibility) */
29
- get statusCode(): number;
30
- /** HTTP status message (alias for compatibility) */
31
- get statusMessage(): string;
32
- /** Structured data for serialization */
33
- get data(): {
34
- why?: string;
35
- fix?: string;
36
- link?: string;
37
- } | undefined;
38
- toString(): string;
39
- toJSON(): Record<string, unknown>;
40
- }
41
- /**
42
- * Create a structured error with context for debugging and user-facing messages.
43
- *
44
- * @param options - Error message string or full options object
45
- * @returns EvlogError with HTTP metadata (`status`, `statusText`) and `data`; also includes `statusCode` and `statusMessage` for legacy compatibility
46
- *
47
- * @example
48
- * ```ts
49
- * // Simple error
50
- * throw createError('Something went wrong')
51
- *
52
- * // Structured error with context
53
- * throw createError({
54
- * message: 'Payment failed',
55
- * status: 402,
56
- * why: 'Card declined by issuer',
57
- * fix: 'Try a different payment method',
58
- * link: 'https://docs.example.com/payments',
59
- * })
60
- * ```
61
- */
62
- declare function createError(options: ErrorOptions | string): EvlogError;
63
- //#endregion
64
- export { EvlogError, createError, createError as createEvlogError };
65
- //# sourceMappingURL=error.d.mts.map
1
+ import { n as createError, t as EvlogError } from "./error-iV3zJCY3.mjs";
2
+ export { EvlogError, createError, createError as createEvlogError };
package/dist/error.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  import { colors, isServer } from "./utils.mjs";
2
-
3
2
  //#region src/error.ts
4
3
  /**
5
4
  * Structured error with context for better debugging
@@ -106,7 +105,7 @@ var EvlogError = class EvlogError extends Error {
106
105
  function createError(options) {
107
106
  return new EvlogError(options);
108
107
  }
109
-
110
108
  //#endregion
111
109
  export { EvlogError, createError, createError as createEvlogError };
110
+
112
111
  //# sourceMappingURL=error.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.mjs","names":[],"sources":["../src/error.ts"],"sourcesContent":["import type { ErrorOptions } from './types'\nimport { colors, isServer } from './utils'\n\n/**\n * Structured error with context for better debugging\n *\n * @example\n * ```ts\n * throw new EvlogError({\n * message: 'Failed to sync repository',\n * status: 503,\n * why: 'GitHub API rate limit exceeded',\n * fix: 'Wait 1 hour or use a different token',\n * link: 'https://docs.github.com/en/rest/rate-limit',\n * cause: originalError,\n * })\n * ```\n */\nexport class EvlogError extends Error {\n\n /** HTTP status code */\n readonly status: number\n readonly why?: string\n readonly fix?: string\n readonly link?: string\n\n constructor(options: ErrorOptions | string) {\n const opts = typeof options === 'string' ? { message: options } : options\n\n super(opts.message, { cause: opts.cause })\n\n this.name = 'EvlogError'\n this.status = opts.status ?? 500\n this.why = opts.why\n this.fix = opts.fix\n this.link = opts.link\n\n // Maintain proper stack trace in V8\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EvlogError)\n }\n }\n\n /** HTTP status text (alias for message) */\n get statusText(): string {\n return this.message\n }\n\n /** HTTP status code (alias for compatibility) */\n get statusCode(): number {\n return this.status\n }\n\n /** HTTP status message (alias for compatibility) */\n get statusMessage(): string {\n return this.message\n }\n\n /** Structured data for serialization */\n get data(): { why?: string, fix?: string, link?: string } | undefined {\n if (this.why || this.fix || this.link) {\n return { why: this.why, fix: this.fix, link: this.link }\n }\n return undefined\n }\n\n override toString(): string {\n const useColors = isServer()\n\n const red = useColors ? colors.red : ''\n const yellow = useColors ? colors.yellow : ''\n const cyan = useColors ? colors.cyan : ''\n const dim = useColors ? colors.dim : ''\n const reset = useColors ? colors.reset : ''\n const bold = useColors ? colors.bold : ''\n\n const lines: string[] = []\n\n lines.push(`${red}${bold}Error:${reset} ${this.message}`)\n\n if (this.why) {\n lines.push(`${yellow}Why:${reset} ${this.why}`)\n }\n\n if (this.fix) {\n lines.push(`${cyan}Fix:${reset} ${this.fix}`)\n }\n\n if (this.link) {\n lines.push(`${dim}More info:${reset} ${this.link}`)\n }\n\n if (this.cause) {\n lines.push(`${dim}Caused by:${reset} ${(this.cause as Error).message}`)\n }\n\n return lines.join('\\n')\n }\n\n toJSON(): Record<string, unknown> {\n const { data } = this\n return {\n name: this.name,\n message: this.message,\n status: this.status,\n ...(data && { data }),\n ...(this.cause instanceof Error && {\n cause: { name: this.cause.name, message: this.cause.message },\n }),\n }\n }\n\n}\n\n/**\n * Create a structured error with context for debugging and user-facing messages.\n *\n * @param options - Error message string or full options object\n * @returns EvlogError with HTTP metadata (`status`, `statusText`) and `data`; also includes `statusCode` and `statusMessage` for legacy compatibility\n *\n * @example\n * ```ts\n * // Simple error\n * throw createError('Something went wrong')\n *\n * // Structured error with context\n * throw createError({\n * message: 'Payment failed',\n * status: 402,\n * why: 'Card declined by issuer',\n * fix: 'Try a different payment method',\n * link: 'https://docs.example.com/payments',\n * })\n * ```\n */\nexport function createError(options: ErrorOptions | string): EvlogError {\n return new EvlogError(options)\n}\n\nexport { createError as createEvlogError }\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,IAAa,aAAb,MAAa,mBAAmB,MAAM;;CAGpC,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CAET,YAAY,SAAgC;EAC1C,MAAM,OAAO,OAAO,YAAY,WAAW,EAAE,SAAS,SAAS,GAAG;AAElE,QAAM,KAAK,SAAS,EAAE,OAAO,KAAK,OAAO,CAAC;AAE1C,OAAK,OAAO;AACZ,OAAK,SAAS,KAAK,UAAU;AAC7B,OAAK,MAAM,KAAK;AAChB,OAAK,MAAM,KAAK;AAChB,OAAK,OAAO,KAAK;AAGjB,MAAI,MAAM,kBACR,OAAM,kBAAkB,MAAM,WAAW;;;CAK7C,IAAI,aAAqB;AACvB,SAAO,KAAK;;;CAId,IAAI,aAAqB;AACvB,SAAO,KAAK;;;CAId,IAAI,gBAAwB;AAC1B,SAAO,KAAK;;;CAId,IAAI,OAAkE;AACpE,MAAI,KAAK,OAAO,KAAK,OAAO,KAAK,KAC/B,QAAO;GAAE,KAAK,KAAK;GAAK,KAAK,KAAK;GAAK,MAAM,KAAK;GAAM;;CAK5D,AAAS,WAAmB;EAC1B,MAAM,YAAY,UAAU;EAE5B,MAAM,MAAM,YAAY,OAAO,MAAM;EACrC,MAAM,SAAS,YAAY,OAAO,SAAS;EAC3C,MAAM,OAAO,YAAY,OAAO,OAAO;EACvC,MAAM,MAAM,YAAY,OAAO,MAAM;EACrC,MAAM,QAAQ,YAAY,OAAO,QAAQ;EACzC,MAAM,OAAO,YAAY,OAAO,OAAO;EAEvC,MAAM,QAAkB,EAAE;AAE1B,QAAM,KAAK,GAAG,MAAM,KAAK,QAAQ,MAAM,GAAG,KAAK,UAAU;AAEzD,MAAI,KAAK,IACP,OAAM,KAAK,GAAG,OAAO,MAAM,MAAM,GAAG,KAAK,MAAM;AAGjD,MAAI,KAAK,IACP,OAAM,KAAK,GAAG,KAAK,MAAM,MAAM,GAAG,KAAK,MAAM;AAG/C,MAAI,KAAK,KACP,OAAM,KAAK,GAAG,IAAI,YAAY,MAAM,GAAG,KAAK,OAAO;AAGrD,MAAI,KAAK,MACP,OAAM,KAAK,GAAG,IAAI,YAAY,MAAM,GAAI,KAAK,MAAgB,UAAU;AAGzE,SAAO,MAAM,KAAK,KAAK;;CAGzB,SAAkC;EAChC,MAAM,EAAE,SAAS;AACjB,SAAO;GACL,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,GAAI,QAAQ,EAAE,MAAM;GACpB,GAAI,KAAK,iBAAiB,SAAS,EACjC,OAAO;IAAE,MAAM,KAAK,MAAM;IAAM,SAAS,KAAK,MAAM;IAAS,EAC9D;GACF;;;;;;;;;;;;;;;;;;;;;;;;AA0BL,SAAgB,YAAY,SAA4C;AACtE,QAAO,IAAI,WAAW,QAAQ"}
1
+ {"version":3,"file":"error.mjs","names":[],"sources":["../src/error.ts"],"sourcesContent":["import type { ErrorOptions } from './types'\nimport { colors, isServer } from './utils'\n\n/**\n * Structured error with context for better debugging\n *\n * @example\n * ```ts\n * throw new EvlogError({\n * message: 'Failed to sync repository',\n * status: 503,\n * why: 'GitHub API rate limit exceeded',\n * fix: 'Wait 1 hour or use a different token',\n * link: 'https://docs.github.com/en/rest/rate-limit',\n * cause: originalError,\n * })\n * ```\n */\nexport class EvlogError extends Error {\n\n /** HTTP status code */\n readonly status: number\n readonly why?: string\n readonly fix?: string\n readonly link?: string\n\n constructor(options: ErrorOptions | string) {\n const opts = typeof options === 'string' ? { message: options } : options\n\n super(opts.message, { cause: opts.cause })\n\n this.name = 'EvlogError'\n this.status = opts.status ?? 500\n this.why = opts.why\n this.fix = opts.fix\n this.link = opts.link\n\n // Maintain proper stack trace in V8\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EvlogError)\n }\n }\n\n /** HTTP status text (alias for message) */\n get statusText(): string {\n return this.message\n }\n\n /** HTTP status code (alias for compatibility) */\n get statusCode(): number {\n return this.status\n }\n\n /** HTTP status message (alias for compatibility) */\n get statusMessage(): string {\n return this.message\n }\n\n /** Structured data for serialization */\n get data(): { why?: string, fix?: string, link?: string } | undefined {\n if (this.why || this.fix || this.link) {\n return { why: this.why, fix: this.fix, link: this.link }\n }\n return undefined\n }\n\n override toString(): string {\n const useColors = isServer()\n\n const red = useColors ? colors.red : ''\n const yellow = useColors ? colors.yellow : ''\n const cyan = useColors ? colors.cyan : ''\n const dim = useColors ? colors.dim : ''\n const reset = useColors ? colors.reset : ''\n const bold = useColors ? colors.bold : ''\n\n const lines: string[] = []\n\n lines.push(`${red}${bold}Error:${reset} ${this.message}`)\n\n if (this.why) {\n lines.push(`${yellow}Why:${reset} ${this.why}`)\n }\n\n if (this.fix) {\n lines.push(`${cyan}Fix:${reset} ${this.fix}`)\n }\n\n if (this.link) {\n lines.push(`${dim}More info:${reset} ${this.link}`)\n }\n\n if (this.cause) {\n lines.push(`${dim}Caused by:${reset} ${(this.cause as Error).message}`)\n }\n\n return lines.join('\\n')\n }\n\n toJSON(): Record<string, unknown> {\n const { data } = this\n return {\n name: this.name,\n message: this.message,\n status: this.status,\n ...(data && { data }),\n ...(this.cause instanceof Error && {\n cause: { name: this.cause.name, message: this.cause.message },\n }),\n }\n }\n\n}\n\n/**\n * Create a structured error with context for debugging and user-facing messages.\n *\n * @param options - Error message string or full options object\n * @returns EvlogError with HTTP metadata (`status`, `statusText`) and `data`; also includes `statusCode` and `statusMessage` for legacy compatibility\n *\n * @example\n * ```ts\n * // Simple error\n * throw createError('Something went wrong')\n *\n * // Structured error with context\n * throw createError({\n * message: 'Payment failed',\n * status: 402,\n * why: 'Card declined by issuer',\n * fix: 'Try a different payment method',\n * link: 'https://docs.example.com/payments',\n * })\n * ```\n */\nexport function createError(options: ErrorOptions | string): EvlogError {\n return new EvlogError(options)\n}\n\nexport { createError as createEvlogError }\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,IAAa,aAAb,MAAa,mBAAmB,MAAM;;CAGpC;CACA;CACA;CACA;CAEA,YAAY,SAAgC;EAC1C,MAAM,OAAO,OAAO,YAAY,WAAW,EAAE,SAAS,SAAS,GAAG;AAElE,QAAM,KAAK,SAAS,EAAE,OAAO,KAAK,OAAO,CAAC;AAE1C,OAAK,OAAO;AACZ,OAAK,SAAS,KAAK,UAAU;AAC7B,OAAK,MAAM,KAAK;AAChB,OAAK,MAAM,KAAK;AAChB,OAAK,OAAO,KAAK;AAGjB,MAAI,MAAM,kBACR,OAAM,kBAAkB,MAAM,WAAW;;;CAK7C,IAAI,aAAqB;AACvB,SAAO,KAAK;;;CAId,IAAI,aAAqB;AACvB,SAAO,KAAK;;;CAId,IAAI,gBAAwB;AAC1B,SAAO,KAAK;;;CAId,IAAI,OAAkE;AACpE,MAAI,KAAK,OAAO,KAAK,OAAO,KAAK,KAC/B,QAAO;GAAE,KAAK,KAAK;GAAK,KAAK,KAAK;GAAK,MAAM,KAAK;GAAM;;CAK5D,WAA4B;EAC1B,MAAM,YAAY,UAAU;EAE5B,MAAM,MAAM,YAAY,OAAO,MAAM;EACrC,MAAM,SAAS,YAAY,OAAO,SAAS;EAC3C,MAAM,OAAO,YAAY,OAAO,OAAO;EACvC,MAAM,MAAM,YAAY,OAAO,MAAM;EACrC,MAAM,QAAQ,YAAY,OAAO,QAAQ;EACzC,MAAM,OAAO,YAAY,OAAO,OAAO;EAEvC,MAAM,QAAkB,EAAE;AAE1B,QAAM,KAAK,GAAG,MAAM,KAAK,QAAQ,MAAM,GAAG,KAAK,UAAU;AAEzD,MAAI,KAAK,IACP,OAAM,KAAK,GAAG,OAAO,MAAM,MAAM,GAAG,KAAK,MAAM;AAGjD,MAAI,KAAK,IACP,OAAM,KAAK,GAAG,KAAK,MAAM,MAAM,GAAG,KAAK,MAAM;AAG/C,MAAI,KAAK,KACP,OAAM,KAAK,GAAG,IAAI,YAAY,MAAM,GAAG,KAAK,OAAO;AAGrD,MAAI,KAAK,MACP,OAAM,KAAK,GAAG,IAAI,YAAY,MAAM,GAAI,KAAK,MAAgB,UAAU;AAGzE,SAAO,MAAM,KAAK,KAAK;;CAGzB,SAAkC;EAChC,MAAM,EAAE,SAAS;AACjB,SAAO;GACL,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,GAAI,QAAQ,EAAE,MAAM;GACpB,GAAI,KAAK,iBAAiB,SAAS,EACjC,OAAO;IAAE,MAAM,KAAK,MAAM;IAAM,SAAS,KAAK,MAAM;IAAS,EAC9D;GACF;;;;;;;;;;;;;;;;;;;;;;;;AA0BL,SAAgB,YAAY,SAA4C;AACtE,QAAO,IAAI,WAAW,QAAQ"}
@@ -0,0 +1,18 @@
1
+ //#region src/shared/errors.ts
2
+ /**
3
+ * Extract HTTP status from an error, checking both `status` and `statusCode`.
4
+ *
5
+ * Works with any error shape (H3, Nitro, EvlogError, plain objects).
6
+ *
7
+ * @beta This function is part of the evlog toolkit API for building custom framework integrations.
8
+ */
9
+ function extractErrorStatus(error) {
10
+ if (error === null || typeof error !== "object") return 500;
11
+ const raw = error.status ?? error.statusCode;
12
+ const status = Number(raw);
13
+ return Number.isFinite(status) ? status : 500;
14
+ }
15
+ //#endregion
16
+ export { extractErrorStatus as t };
17
+
18
+ //# sourceMappingURL=errors-BJRXUfMg.mjs.map
@@ -0,0 +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"}
@@ -0,0 +1,39 @@
1
+ import { v as RouteConfig } from "./types-B8-kC2ME.mjs";
2
+
3
+ //#region src/shared/routes.d.ts
4
+ declare function shouldLog(path: string, include?: string[], exclude?: string[]): boolean;
5
+ /**
6
+ * Find the service name for a given path based on route patterns.
7
+ *
8
+ * When multiple patterns match the same path, the first matching pattern wins
9
+ * based on object iteration order. To ensure predictable behavior, order your
10
+ * route patterns from most specific to most general.
11
+ *
12
+ * @param path - The request path to match
13
+ * @param routes - Route configuration mapping patterns to service names
14
+ * @returns The service name for the matching route, or undefined if no match
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * // Good: specific patterns first, general patterns last
19
+ * routes: {
20
+ * '/api/auth/admin/**': { service: 'admin-service' },
21
+ * '/api/auth/**': { service: 'auth-service' },
22
+ * '/api/**': { service: 'api-service' },
23
+ * }
24
+ * ```
25
+ */
26
+ declare function getServiceForPath(path: string, routes?: Record<string, RouteConfig>): string | undefined;
27
+ //#endregion
28
+ //#region src/shared/errors.d.ts
29
+ /**
30
+ * Extract HTTP status from an error, checking both `status` and `statusCode`.
31
+ *
32
+ * Works with any error shape (H3, Nitro, EvlogError, plain objects).
33
+ *
34
+ * @beta This function is part of the evlog toolkit API for building custom framework integrations.
35
+ */
36
+ declare function extractErrorStatus(error: unknown): number;
37
+ //#endregion
38
+ export { getServiceForPath as n, shouldLog as r, extractErrorStatus as t };
39
+ //# sourceMappingURL=errors-CKSfdvLa.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-CKSfdvLa.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 { RequestLogger } from "../types.mjs";
2
- import { t as BaseEvlogOptions } from "../middleware-BoVCgsfQ.mjs";
1
+ import { g as RequestLogger } from "../types-B8-kC2ME.mjs";
2
+ import { t as BaseEvlogOptions } from "../middleware-hZqyXoSk.mjs";
3
3
  import { RequestHandler } from "express";
4
4
 
5
5
  //#region src/express/index.d.ts
@@ -1,6 +1,5 @@
1
- import { n as extractSafeNodeHeaders, r as createMiddlewareLogger } from "../headers-CXOd5EyZ.mjs";
2
- import { t as createLoggerStorage } from "../storage-CejtuV76.mjs";
3
-
1
+ import { n as extractSafeNodeHeaders, r as createMiddlewareLogger } from "../headers-Ba1eKT3i.mjs";
2
+ import { t as createLoggerStorage } from "../storage-CJBW5Vos.mjs";
4
3
  //#region src/express/index.ts
5
4
  const { storage, useLogger } = createLoggerStorage("middleware context. Make sure app.use(evlog()) is registered before your routes.");
6
5
  /**
@@ -41,7 +40,7 @@ function evlog(options = {}) {
41
40
  storage.run(logger, () => next());
42
41
  };
43
42
  }
44
-
45
43
  //#endregion
46
44
  export { evlog, useLogger };
45
+
47
46
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/express/index.ts"],"sourcesContent":["import type { Request, Response, NextFunction, RequestHandler } from 'express'\nimport type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { extractSafeNodeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'middleware context. Make sure app.use(evlog()) is registered before your routes.',\n)\n\nexport type EvlogExpressOptions = BaseEvlogOptions\n\nexport { useLogger }\n\ndeclare module 'express-serve-static-core' {\n interface Request {\n log: RequestLogger\n }\n}\n\n/**\n * Create an evlog middleware for Express.\n *\n * @example\n * ```ts\n * import express from 'express'\n * import { evlog } from 'evlog/express'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * const app = express()\n * app.use(evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * }))\n * ```\n */\nexport function evlog(options: EvlogExpressOptions = {}): RequestHandler {\n return (req: Request, res: Response, next: NextFunction) => {\n const { logger, finish, skipped } = createMiddlewareLogger({\n method: req.method,\n path: req.path,\n requestId: req.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeNodeHeaders(req.headers),\n ...options,\n })\n\n if (skipped) {\n next()\n return\n }\n\n req.log = logger\n\n res.on('finish', () => {\n finish({ status: res.statusCode }).catch(() => {})\n })\n\n storage.run(logger, () => next())\n }\n}\n"],"mappings":";;;;AAMA,MAAM,EAAE,SAAS,cAAc,oBAC7B,mFACD;;;;;;;;;;;;;;;;;;;AA8BD,SAAgB,MAAM,UAA+B,EAAE,EAAkB;AACvE,SAAQ,KAAc,KAAe,SAAuB;EAC1D,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,IAAI;GACZ,MAAM,IAAI;GACV,WAAW,IAAI,IAAI,eAAe,IAAI,OAAO,YAAY;GACzD,SAAS,uBAAuB,IAAI,QAAQ;GAC5C,GAAG;GACJ,CAAC;AAEF,MAAI,SAAS;AACX,SAAM;AACN;;AAGF,MAAI,MAAM;AAEV,MAAI,GAAG,gBAAgB;AACrB,UAAO,EAAE,QAAQ,IAAI,YAAY,CAAC,CAAC,YAAY,GAAG;IAClD;AAEF,UAAQ,IAAI,cAAc,MAAM,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/express/index.ts"],"sourcesContent":["import type { Request, Response, NextFunction, RequestHandler } from 'express'\nimport type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { extractSafeNodeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'middleware context. Make sure app.use(evlog()) is registered before your routes.',\n)\n\nexport type EvlogExpressOptions = BaseEvlogOptions\n\nexport { useLogger }\n\ndeclare module 'express-serve-static-core' {\n interface Request {\n log: RequestLogger\n }\n}\n\n/**\n * Create an evlog middleware for Express.\n *\n * @example\n * ```ts\n * import express from 'express'\n * import { evlog } from 'evlog/express'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * const app = express()\n * app.use(evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * }))\n * ```\n */\nexport function evlog(options: EvlogExpressOptions = {}): RequestHandler {\n return (req: Request, res: Response, next: NextFunction) => {\n const { logger, finish, skipped } = createMiddlewareLogger({\n method: req.method,\n path: req.path,\n requestId: req.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeNodeHeaders(req.headers),\n ...options,\n })\n\n if (skipped) {\n next()\n return\n }\n\n req.log = logger\n\n res.on('finish', () => {\n finish({ status: res.statusCode }).catch(() => {})\n })\n\n storage.run(logger, () => next())\n }\n}\n"],"mappings":";;;AAMA,MAAM,EAAE,SAAS,cAAc,oBAC7B,mFACD;;;;;;;;;;;;;;;;;;;AA8BD,SAAgB,MAAM,UAA+B,EAAE,EAAkB;AACvE,SAAQ,KAAc,KAAe,SAAuB;EAC1D,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,IAAI;GACZ,MAAM,IAAI;GACV,WAAW,IAAI,IAAI,eAAe,IAAI,OAAO,YAAY;GACzD,SAAS,uBAAuB,IAAI,QAAQ;GAC5C,GAAG;GACJ,CAAC;AAEF,MAAI,SAAS;AACX,SAAM;AACN;;AAGF,MAAI,MAAM;AAEV,MAAI,GAAG,gBAAgB;AACrB,UAAO,EAAE,QAAQ,IAAI,YAAY,CAAC,CAAC,YAAY,GAAG;IAClD;AAEF,UAAQ,IAAI,cAAc,MAAM,CAAC"}
@@ -1,5 +1,5 @@
1
- import { RequestLogger } from "../types.mjs";
2
- import { t as BaseEvlogOptions } from "../middleware-BoVCgsfQ.mjs";
1
+ import { g as RequestLogger } from "../types-B8-kC2ME.mjs";
2
+ import { t as BaseEvlogOptions } from "../middleware-hZqyXoSk.mjs";
3
3
  import { FastifyPluginCallback } from "fastify";
4
4
 
5
5
  //#region src/fastify/index.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/fastify/index.ts"],"mappings":";;;;;cAKiB,SAAA,sBAAS,MAAA,wBAAA,aAAA,CAAA,CAAA;AAAA,KAId,mBAAA,GAAsB,gBAAA;AAAA;EAAA,UAKtB,cAAA;IAER,GAAA;EAAA;AAAA;;;;;;;;;;;AAPJ;;;;;AAEoB;;;;;;cAyFP,KAAA,EAAK,qBAAA,CAAA,gBAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/fastify/index.ts"],"mappings":";;;;;cAKiB,SAAA,sBAAS,MAAA,wBAAA,aAAA,CAAA,CAAA;AAAA,KAId,mBAAA,GAAsB,gBAAA;AAAA;EAAA,UAKtB,cAAA;IAER,GAAA;EAAA;AAAA;AAfgF;;;;;;;;;;;;;;AAQpF;;;;;AAEoB;;AAVgE,cAmGvE,KAAA,EAAK,qBAAA,CAAA,gBAAA"}
@@ -1,6 +1,5 @@
1
- import { n as extractSafeNodeHeaders, r as createMiddlewareLogger } from "../headers-CXOd5EyZ.mjs";
2
- import { t as createLoggerStorage } from "../storage-CejtuV76.mjs";
3
-
1
+ import { n as extractSafeNodeHeaders, r as createMiddlewareLogger } from "../headers-Ba1eKT3i.mjs";
2
+ import { t as createLoggerStorage } from "../storage-CJBW5Vos.mjs";
4
3
  //#region src/fastify/index.ts
5
4
  const { storage, useLogger } = createLoggerStorage("plugin context. Make sure app.register(evlog) is called before your routes.");
6
5
  const evlogPlugin = (fastify, options, done) => {
@@ -67,7 +66,7 @@ plugin[Symbol.for("fastify.display-name")] = "evlog";
67
66
  * ```
68
67
  */
69
68
  const evlog = evlogPlugin;
70
-
71
69
  //#endregion
72
70
  export { evlog, useLogger };
71
+
73
72
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/fastify/index.ts"],"sourcesContent":["import type { FastifyPluginCallback } from 'fastify'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { extractSafeNodeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'plugin context. Make sure app.register(evlog) is called before your routes.',\n)\n\nexport type EvlogFastifyOptions = BaseEvlogOptions\n\nexport { useLogger }\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n // Overrides Fastify's built-in pino logger on the request with evlog's RequestLogger.\n log: any\n }\n}\n\ninterface RequestState {\n finish: (opts?: { status?: number; error?: Error }) => Promise<unknown>\n}\n\nconst evlogPlugin: FastifyPluginCallback<EvlogFastifyOptions> = (fastify, options, done) => {\n const emitted = new WeakSet<object>()\n const requestState = new WeakMap<object, RequestState>()\n\n fastify.addHook('onRequest', (request, _reply, done) => {\n const headers = extractSafeNodeHeaders(request.headers)\n const path = new URL(request.url, 'http://localhost').pathname\n\n const { logger, finish, skipped } = createMiddlewareLogger({\n method: request.method,\n path,\n requestId: headers['x-request-id'] || crypto.randomUUID(),\n headers,\n ...options,\n })\n\n if (skipped) {\n done()\n return\n }\n\n // Shadow Fastify's built-in pino logger with evlog's request-scoped logger\n const req = request as any\n req.log = logger\n requestState.set(request, { finish })\n\n storage.run(logger, () => done())\n })\n\n fastify.addHook('onResponse', async (request, reply) => {\n const state = requestState.get(request)\n if (!state || emitted.has(request)) return\n emitted.add(request)\n await state.finish({ status: reply.statusCode })\n })\n\n fastify.addHook('onError', async (request, _reply, error) => {\n const state = requestState.get(request)\n if (!state || emitted.has(request)) return\n emitted.add(request)\n const logger = (request as any).log\n const err = error instanceof Error ? error : new Error(String(error))\n if (logger && typeof logger.error === 'function') logger.error(err)\n await state.finish({ error: err })\n })\n\n done()\n}\n\n// Break Fastify plugin encapsulation without a runtime dependency on fastify-plugin.\n// This is the same mechanism fastify-plugin uses internally.\nconst plugin = evlogPlugin as any\nplugin[Symbol.for('skip-override')] = true\nplugin[Symbol.for('fastify.display-name')] = 'evlog'\n\n/**\n * Create an evlog plugin for Fastify.\n *\n * @example\n * ```ts\n * import Fastify from 'fastify'\n * import { initLogger } from 'evlog'\n * import { evlog } from 'evlog/fastify'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'fastify-api' } })\n *\n * const app = Fastify()\n * await app.register(evlog, {\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n */\nexport const evlog = evlogPlugin\n"],"mappings":";;;;AAKA,MAAM,EAAE,SAAS,cAAc,oBAC7B,8EACD;AAiBD,MAAM,eAA2D,SAAS,SAAS,SAAS;CAC1F,MAAM,0BAAU,IAAI,SAAiB;CACrC,MAAM,+BAAe,IAAI,SAA+B;AAExD,SAAQ,QAAQ,cAAc,SAAS,QAAQ,SAAS;EACtD,MAAM,UAAU,uBAAuB,QAAQ,QAAQ;EACvD,MAAM,OAAO,IAAI,IAAI,QAAQ,KAAK,mBAAmB,CAAC;EAEtD,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,QAAQ;GAChB;GACA,WAAW,QAAQ,mBAAmB,OAAO,YAAY;GACzD;GACA,GAAG;GACJ,CAAC;AAEF,MAAI,SAAS;AACX,SAAM;AACN;;EAIF,MAAM,MAAM;AACZ,MAAI,MAAM;AACV,eAAa,IAAI,SAAS,EAAE,QAAQ,CAAC;AAErC,UAAQ,IAAI,cAAc,MAAM,CAAC;GACjC;AAEF,SAAQ,QAAQ,cAAc,OAAO,SAAS,UAAU;EACtD,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,QAAQ,IAAI,QAAQ,CAAE;AACpC,UAAQ,IAAI,QAAQ;AACpB,QAAM,MAAM,OAAO,EAAE,QAAQ,MAAM,YAAY,CAAC;GAChD;AAEF,SAAQ,QAAQ,WAAW,OAAO,SAAS,QAAQ,UAAU;EAC3D,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,QAAQ,IAAI,QAAQ,CAAE;AACpC,UAAQ,IAAI,QAAQ;EACpB,MAAM,SAAU,QAAgB;EAChC,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AACrE,MAAI,UAAU,OAAO,OAAO,UAAU,WAAY,QAAO,MAAM,IAAI;AACnE,QAAM,MAAM,OAAO,EAAE,OAAO,KAAK,CAAC;GAClC;AAEF,OAAM;;AAKR,MAAM,SAAS;AACf,OAAO,OAAO,IAAI,gBAAgB,IAAI;AACtC,OAAO,OAAO,IAAI,uBAAuB,IAAI;;;;;;;;;;;;;;;;;;;;;;AAuB7C,MAAa,QAAQ"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/fastify/index.ts"],"sourcesContent":["import type { FastifyPluginCallback } from 'fastify'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { extractSafeNodeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'plugin context. Make sure app.register(evlog) is called before your routes.',\n)\n\nexport type EvlogFastifyOptions = BaseEvlogOptions\n\nexport { useLogger }\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n // Overrides Fastify's built-in pino logger on the request with evlog's RequestLogger.\n log: any\n }\n}\n\ninterface RequestState {\n finish: (opts?: { status?: number; error?: Error }) => Promise<unknown>\n}\n\nconst evlogPlugin: FastifyPluginCallback<EvlogFastifyOptions> = (fastify, options, done) => {\n const emitted = new WeakSet<object>()\n const requestState = new WeakMap<object, RequestState>()\n\n fastify.addHook('onRequest', (request, _reply, done) => {\n const headers = extractSafeNodeHeaders(request.headers)\n const path = new URL(request.url, 'http://localhost').pathname\n\n const { logger, finish, skipped } = createMiddlewareLogger({\n method: request.method,\n path,\n requestId: headers['x-request-id'] || crypto.randomUUID(),\n headers,\n ...options,\n })\n\n if (skipped) {\n done()\n return\n }\n\n // Shadow Fastify's built-in pino logger with evlog's request-scoped logger\n const req = request as any\n req.log = logger\n requestState.set(request, { finish })\n\n storage.run(logger, () => done())\n })\n\n fastify.addHook('onResponse', async (request, reply) => {\n const state = requestState.get(request)\n if (!state || emitted.has(request)) return\n emitted.add(request)\n await state.finish({ status: reply.statusCode })\n })\n\n fastify.addHook('onError', async (request, _reply, error) => {\n const state = requestState.get(request)\n if (!state || emitted.has(request)) return\n emitted.add(request)\n const logger = (request as any).log\n const err = error instanceof Error ? error : new Error(String(error))\n if (logger && typeof logger.error === 'function') logger.error(err)\n await state.finish({ error: err })\n })\n\n done()\n}\n\n// Break Fastify plugin encapsulation without a runtime dependency on fastify-plugin.\n// This is the same mechanism fastify-plugin uses internally.\nconst plugin = evlogPlugin as any\nplugin[Symbol.for('skip-override')] = true\nplugin[Symbol.for('fastify.display-name')] = 'evlog'\n\n/**\n * Create an evlog plugin for Fastify.\n *\n * @example\n * ```ts\n * import Fastify from 'fastify'\n * import { initLogger } from 'evlog'\n * import { evlog } from 'evlog/fastify'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'fastify-api' } })\n *\n * const app = Fastify()\n * await app.register(evlog, {\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n */\nexport const evlog = evlogPlugin\n"],"mappings":";;;AAKA,MAAM,EAAE,SAAS,cAAc,oBAC7B,8EACD;AAiBD,MAAM,eAA2D,SAAS,SAAS,SAAS;CAC1F,MAAM,0BAAU,IAAI,SAAiB;CACrC,MAAM,+BAAe,IAAI,SAA+B;AAExD,SAAQ,QAAQ,cAAc,SAAS,QAAQ,SAAS;EACtD,MAAM,UAAU,uBAAuB,QAAQ,QAAQ;EACvD,MAAM,OAAO,IAAI,IAAI,QAAQ,KAAK,mBAAmB,CAAC;EAEtD,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,QAAQ;GAChB;GACA,WAAW,QAAQ,mBAAmB,OAAO,YAAY;GACzD;GACA,GAAG;GACJ,CAAC;AAEF,MAAI,SAAS;AACX,SAAM;AACN;;EAIF,MAAM,MAAM;AACZ,MAAI,MAAM;AACV,eAAa,IAAI,SAAS,EAAE,QAAQ,CAAC;AAErC,UAAQ,IAAI,cAAc,MAAM,CAAC;GACjC;AAEF,SAAQ,QAAQ,cAAc,OAAO,SAAS,UAAU;EACtD,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,QAAQ,IAAI,QAAQ,CAAE;AACpC,UAAQ,IAAI,QAAQ;AACpB,QAAM,MAAM,OAAO,EAAE,QAAQ,MAAM,YAAY,CAAC;GAChD;AAEF,SAAQ,QAAQ,WAAW,OAAO,SAAS,QAAQ,UAAU;EAC3D,MAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,MAAI,CAAC,SAAS,QAAQ,IAAI,QAAQ,CAAE;AACpC,UAAQ,IAAI,QAAQ;EACpB,MAAM,SAAU,QAAgB;EAChC,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AACrE,MAAI,UAAU,OAAO,OAAO,UAAU,WAAY,QAAO,MAAM,IAAI;AACnE,QAAM,MAAM,OAAO,EAAE,OAAO,KAAK,CAAC;GAClC;AAEF,OAAM;;AAKR,MAAM,SAAS;AACf,OAAO,OAAO,IAAI,gBAAgB,IAAI;AACtC,OAAO,OAAO,IAAI,uBAAuB,IAAI;;;;;;;;;;;;;;;;;;;;;;AAuB7C,MAAa,QAAQ"}