evlog 2.14.1 → 2.16.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 (187) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +4 -4
  3. package/dist/adapters/axiom.d.mts +18 -27
  4. package/dist/adapters/axiom.d.mts.map +1 -1
  5. package/dist/adapters/axiom.mjs +40 -30
  6. package/dist/adapters/axiom.mjs.map +1 -1
  7. package/dist/adapters/better-stack.d.mts +11 -24
  8. package/dist/adapters/better-stack.d.mts.map +1 -1
  9. package/dist/adapters/better-stack.mjs +34 -29
  10. package/dist/adapters/better-stack.mjs.map +1 -1
  11. package/dist/adapters/datadog.d.mts +1 -1
  12. package/dist/adapters/datadog.d.mts.map +1 -1
  13. package/dist/adapters/datadog.mjs +10 -4
  14. package/dist/adapters/datadog.mjs.map +1 -1
  15. package/dist/adapters/fs.d.mts +2 -2
  16. package/dist/adapters/fs.d.mts.map +1 -1
  17. package/dist/adapters/fs.mjs +19 -7
  18. package/dist/adapters/fs.mjs.map +1 -1
  19. package/dist/adapters/hyperdx.d.mts +1 -1
  20. package/dist/adapters/hyperdx.mjs +1 -2
  21. package/dist/adapters/hyperdx.mjs.map +1 -1
  22. package/dist/adapters/otlp.d.mts +1 -1
  23. package/dist/adapters/otlp.d.mts.map +1 -1
  24. package/dist/adapters/otlp.mjs +36 -31
  25. package/dist/adapters/otlp.mjs.map +1 -1
  26. package/dist/adapters/posthog.d.mts +50 -70
  27. package/dist/adapters/posthog.d.mts.map +1 -1
  28. package/dist/adapters/posthog.mjs +50 -85
  29. package/dist/adapters/posthog.mjs.map +1 -1
  30. package/dist/adapters/sentry.d.mts +1 -1
  31. package/dist/adapters/sentry.d.mts.map +1 -1
  32. package/dist/adapters/sentry.mjs +15 -5
  33. package/dist/adapters/sentry.mjs.map +1 -1
  34. package/dist/ai/index.d.mts +15 -1
  35. package/dist/ai/index.d.mts.map +1 -1
  36. package/dist/ai/index.mjs +48 -16
  37. package/dist/ai/index.mjs.map +1 -1
  38. package/dist/{audit-CTIviX3P.d.mts → audit-X1uUukm3.d.mts} +145 -2
  39. package/dist/audit-X1uUukm3.d.mts.map +1 -0
  40. package/dist/{audit-DQoBo7Dl.mjs → audit-pV5aLGP0.mjs} +153 -13
  41. package/dist/audit-pV5aLGP0.mjs.map +1 -0
  42. package/dist/better-auth/index.d.mts +1 -1
  43. package/dist/browser.d.mts +1 -1
  44. package/dist/define-CuXOqecD.d.mts +57 -0
  45. package/dist/define-CuXOqecD.d.mts.map +1 -0
  46. package/dist/define-D6OJdSUH.mjs +63 -0
  47. package/dist/define-D6OJdSUH.mjs.map +1 -0
  48. package/dist/{dist-Do8P4zWd.mjs → dist-BIlS38vi.mjs} +1 -1
  49. package/dist/dist-BIlS38vi.mjs.map +1 -0
  50. package/dist/drain-ByWUeOQC.mjs +160 -0
  51. package/dist/drain-ByWUeOQC.mjs.map +1 -0
  52. package/dist/elysia/index.d.mts +25 -2
  53. package/dist/elysia/index.d.mts.map +1 -1
  54. package/dist/elysia/index.mjs +53 -20
  55. package/dist/elysia/index.mjs.map +1 -1
  56. package/dist/enricher-DYTr9I16.d.mts +42 -0
  57. package/dist/enricher-DYTr9I16.d.mts.map +1 -0
  58. package/dist/enricher-Dy06T17G.mjs +95 -0
  59. package/dist/enricher-Dy06T17G.mjs.map +1 -0
  60. package/dist/enrichers.d.mts +16 -9
  61. package/dist/enrichers.d.mts.map +1 -1
  62. package/dist/enrichers.mjs +81 -64
  63. package/dist/enrichers.mjs.map +1 -1
  64. package/dist/{error-C7gSQVqk.d.mts → error-Cpc7RVz6.d.mts} +7 -2
  65. package/dist/error-Cpc7RVz6.d.mts.map +1 -0
  66. package/dist/error.d.mts +1 -1
  67. package/dist/error.mjs +8 -1
  68. package/dist/error.mjs.map +1 -1
  69. package/dist/{errors-BJRXUfMg.mjs → errors-BQgyQ9xe.mjs} +1 -1
  70. package/dist/{errors-BJRXUfMg.mjs.map → errors-BQgyQ9xe.mjs.map} +1 -1
  71. package/dist/{errors-4MPmTzjY.d.mts → errors-prnQ3kES.d.mts} +2 -2
  72. package/dist/{errors-4MPmTzjY.d.mts.map → errors-prnQ3kES.d.mts.map} +1 -1
  73. package/dist/event-DcHmEm3O.mjs +55 -0
  74. package/dist/event-DcHmEm3O.mjs.map +1 -0
  75. package/dist/express/index.d.mts +2 -2
  76. package/dist/express/index.d.mts.map +1 -1
  77. package/dist/express/index.mjs +17 -15
  78. package/dist/express/index.mjs.map +1 -1
  79. package/dist/fastify/index.d.mts +2 -2
  80. package/dist/fastify/index.d.mts.map +1 -1
  81. package/dist/fastify/index.mjs +19 -20
  82. package/dist/fastify/index.mjs.map +1 -1
  83. package/dist/fork-DPN8aL8O.mjs +227 -0
  84. package/dist/fork-DPN8aL8O.mjs.map +1 -0
  85. package/dist/{headers-D74M0wsg.mjs → headers-CU-QqnYg.mjs} +19 -2
  86. package/dist/headers-CU-QqnYg.mjs.map +1 -0
  87. package/dist/hono/index.d.mts +2 -2
  88. package/dist/hono/index.d.mts.map +1 -1
  89. package/dist/hono/index.mjs +14 -10
  90. package/dist/hono/index.mjs.map +1 -1
  91. package/dist/http.d.mts +1 -1
  92. package/dist/index.d.mts +8 -7
  93. package/dist/index.mjs +3 -2
  94. package/dist/integration-DSZPbI9N.mjs +75 -0
  95. package/dist/integration-DSZPbI9N.mjs.map +1 -0
  96. package/dist/{logger-DttRJRGa.d.mts → logger-U8lgdc9x.d.mts} +9 -3
  97. package/dist/logger-U8lgdc9x.d.mts.map +1 -0
  98. package/dist/logger.d.mts +2 -2
  99. package/dist/logger.mjs +2 -2
  100. package/dist/middleware-CAQHJRN1.d.mts +72 -0
  101. package/dist/middleware-CAQHJRN1.d.mts.map +1 -0
  102. package/dist/nestjs/index.d.mts +2 -2
  103. package/dist/nestjs/index.mjs +3 -4
  104. package/dist/nestjs/index.mjs.map +1 -1
  105. package/dist/next/client.d.mts +1 -1
  106. package/dist/next/index.d.mts +4 -4
  107. package/dist/next/index.mjs +3 -3
  108. package/dist/next/instrumentation.d.mts +1 -1
  109. package/dist/next/instrumentation.mjs +1 -1
  110. package/dist/nitro/errorHandler.mjs +2 -2
  111. package/dist/nitro/module.d.mts +2 -2
  112. package/dist/nitro/plugin.mjs +21 -11
  113. package/dist/nitro/plugin.mjs.map +1 -1
  114. package/dist/nitro/v3/errorHandler.mjs +3 -3
  115. package/dist/nitro/v3/index.d.mts +2 -2
  116. package/dist/nitro/v3/module.d.mts +1 -1
  117. package/dist/nitro/v3/plugin.mjs +29 -17
  118. package/dist/nitro/v3/plugin.mjs.map +1 -1
  119. package/dist/nitro/v3/useLogger.d.mts +1 -1
  120. package/dist/{nitro-CPPRCPbG.d.mts → nitro-C6Bd682U.d.mts} +2 -2
  121. package/dist/{nitro-CPPRCPbG.d.mts.map → nitro-C6Bd682U.d.mts.map} +1 -1
  122. package/dist/{nitro-OmT_M4Pb.mjs → nitro-DavLelNz.mjs} +2 -2
  123. package/dist/nitro-DavLelNz.mjs.map +1 -0
  124. package/dist/{nitroConfigBridge-C37lXaNm.mjs → nitroConfigBridge-aZ1e5upQ.mjs} +1 -1
  125. package/dist/nitroConfigBridge-aZ1e5upQ.mjs.map +1 -0
  126. package/dist/nuxt/module.d.mts +1 -1
  127. package/dist/nuxt/module.mjs +2 -2
  128. package/dist/{parseError-o1GpZEOR.d.mts → parseError-B-dKF6Fd.d.mts} +2 -2
  129. package/dist/parseError-B-dKF6Fd.d.mts.map +1 -0
  130. package/dist/react-router/index.d.mts +2 -2
  131. package/dist/react-router/index.mjs +3 -4
  132. package/dist/react-router/index.mjs.map +1 -1
  133. package/dist/{routes-CGPmbzCZ.mjs → routes-B48wm7Pb.mjs} +1 -1
  134. package/dist/{routes-CGPmbzCZ.mjs.map → routes-B48wm7Pb.mjs.map} +1 -1
  135. package/dist/runtime/client/log.d.mts +1 -1
  136. package/dist/runtime/server/routes/_evlog/ingest.post.mjs +21 -10
  137. package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
  138. package/dist/runtime/server/useLogger.d.mts +1 -1
  139. package/dist/runtime/utils/parseError.d.mts +2 -2
  140. package/dist/runtime/utils/parseError.mjs +9 -1
  141. package/dist/runtime/utils/parseError.mjs.map +1 -1
  142. package/dist/{_severity-CQijvfhU.mjs → severity-BYWZ96Sb.mjs} +6 -2
  143. package/dist/severity-BYWZ96Sb.mjs.map +1 -0
  144. package/dist/{source-location-DRvDDqfq.mjs → source-location-Dco0cRTz.mjs} +3 -3
  145. package/dist/source-location-Dco0cRTz.mjs.map +1 -0
  146. package/dist/storage-BT-3fT1-.mjs +27 -0
  147. package/dist/storage-BT-3fT1-.mjs.map +1 -0
  148. package/dist/sveltekit/index.d.mts +2 -2
  149. package/dist/sveltekit/index.mjs +5 -6
  150. package/dist/sveltekit/index.mjs.map +1 -1
  151. package/dist/toolkit.d.mts +288 -12
  152. package/dist/toolkit.d.mts.map +1 -1
  153. package/dist/toolkit.mjs +13 -7
  154. package/dist/types.d.mts +1 -1
  155. package/dist/{useLogger-CyPP1sVB.d.mts → useLogger-CoNgTjp5.d.mts} +2 -2
  156. package/dist/{useLogger-CyPP1sVB.d.mts.map → useLogger-CoNgTjp5.d.mts.map} +1 -1
  157. package/dist/{utils-Dmin7wVL.d.mts → utils-Db4qhBWn.d.mts} +2 -2
  158. package/dist/{utils-Dmin7wVL.d.mts.map → utils-Db4qhBWn.d.mts.map} +1 -1
  159. package/dist/utils.d.mts +1 -1
  160. package/dist/vite/index.d.mts +1 -1
  161. package/dist/vite/index.mjs +1 -1
  162. package/dist/workers.d.mts +1 -1
  163. package/dist/workers.mjs +1 -1
  164. package/package.json +22 -19
  165. package/dist/_drain-CmCtsuF6.mjs +0 -23
  166. package/dist/_drain-CmCtsuF6.mjs.map +0 -1
  167. package/dist/_http-BY1e9pwC.mjs +0 -78
  168. package/dist/_http-BY1e9pwC.mjs.map +0 -1
  169. package/dist/_severity-CQijvfhU.mjs.map +0 -1
  170. package/dist/audit-CTIviX3P.d.mts.map +0 -1
  171. package/dist/audit-DQoBo7Dl.mjs.map +0 -1
  172. package/dist/dist-Do8P4zWd.mjs.map +0 -1
  173. package/dist/error-C7gSQVqk.d.mts.map +0 -1
  174. package/dist/fork-D1j1Fuzy.mjs +0 -72
  175. package/dist/fork-D1j1Fuzy.mjs.map +0 -1
  176. package/dist/headers-D74M0wsg.mjs.map +0 -1
  177. package/dist/logger-DttRJRGa.d.mts.map +0 -1
  178. package/dist/middleware-CTnDsST-.d.mts +0 -93
  179. package/dist/middleware-CTnDsST-.d.mts.map +0 -1
  180. package/dist/middleware-oAccqyPp.mjs +0 -123
  181. package/dist/middleware-oAccqyPp.mjs.map +0 -1
  182. package/dist/nitro-OmT_M4Pb.mjs.map +0 -1
  183. package/dist/nitroConfigBridge-C37lXaNm.mjs.map +0 -1
  184. package/dist/parseError-o1GpZEOR.d.mts.map +0 -1
  185. package/dist/source-location-DRvDDqfq.mjs.map +0 -1
  186. package/dist/storage-CFGTn37X.mjs +0 -46
  187. package/dist/storage-CFGTn37X.mjs.map +0 -1
@@ -0,0 +1,160 @@
1
+ import { t as getNitroRuntimeConfigRecord } from "./nitroConfigBridge-aZ1e5upQ.mjs";
2
+ //#region src/shared/config.ts
3
+ /** Read the full Nitro `useRuntimeConfig()` record (or `undefined` outside Nitro). */
4
+ function getRuntimeConfig() {
5
+ return getNitroRuntimeConfigRecord();
6
+ }
7
+ /**
8
+ * Resolve adapter configuration with the standard priority chain:
9
+ *
10
+ * 1. `overrides` passed to the drain factory
11
+ * 2. `runtimeConfig.evlog.{namespace}.{key}` (Nitro)
12
+ * 3. `runtimeConfig.{namespace}.{key}` (Nitro)
13
+ * 4. `process.env[envKey]` for each env in `field.env`
14
+ */
15
+ async function resolveAdapterConfig(namespace, fields, overrides) {
16
+ const runtimeConfig = shouldProbeRuntimeConfig(fields, overrides) ? await getRuntimeConfig() : void 0;
17
+ const evlogNs = runtimeConfig?.evlog?.[namespace];
18
+ const rootNs = runtimeConfig?.[namespace];
19
+ const config = {};
20
+ for (const { key, env } of fields) config[key] = overrides?.[key] ?? evlogNs?.[key] ?? rootNs?.[key] ?? resolveEnv(env);
21
+ return config;
22
+ }
23
+ function shouldProbeRuntimeConfig(fields, overrides) {
24
+ return fields.some(({ key, env }) => {
25
+ if (overrides?.[key] !== void 0) return false;
26
+ if (!env) return false;
27
+ return resolveEnv(env) === void 0;
28
+ });
29
+ }
30
+ function resolveEnv(envKeys) {
31
+ if (!envKeys) return void 0;
32
+ for (const key of envKeys) {
33
+ const val = process.env[key];
34
+ if (val) return val;
35
+ }
36
+ }
37
+ //#endregion
38
+ //#region src/shared/http.ts
39
+ function isRetryable(error) {
40
+ if (error instanceof DOMException && error.name === "AbortError") return true;
41
+ if (error instanceof TypeError) return true;
42
+ if (error instanceof Error) {
43
+ const match = error.message.match(/API error: (\d+)/);
44
+ if (match) return Number.parseInt(match[1]) >= 500;
45
+ }
46
+ return false;
47
+ }
48
+ /**
49
+ * POST a body with timeout + retry. Throws label-prefixed errors with a
50
+ * truncated response body. Safe to call from any drain `send()`.
51
+ */
52
+ async function httpPost({ url, headers, body, timeout, label, retries = 2 }) {
53
+ const normalizedRetries = Number.isFinite(retries) && retries >= 0 ? Math.floor(retries) : 2;
54
+ let lastError;
55
+ for (let attempt = 0; attempt <= normalizedRetries; attempt++) {
56
+ const controller = new AbortController();
57
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
58
+ try {
59
+ const response = await fetch(url, {
60
+ method: "POST",
61
+ headers,
62
+ body,
63
+ signal: controller.signal
64
+ });
65
+ if (!response.ok) {
66
+ const text = await response.text().catch(() => "Unknown error");
67
+ const safeText = text.length > 200 ? `${text.slice(0, 200)}...[truncated]` : text;
68
+ throw new Error(`${label} API error: ${response.status} ${response.statusText} - ${safeText}`);
69
+ }
70
+ clearTimeout(timeoutId);
71
+ return;
72
+ } catch (error) {
73
+ clearTimeout(timeoutId);
74
+ if (error instanceof DOMException && error.name === "AbortError") lastError = /* @__PURE__ */ new Error(`${label} request timed out after ${timeout}ms`);
75
+ else lastError = error;
76
+ if (!isRetryable(error) || attempt === normalizedRetries) throw lastError;
77
+ await new Promise((r) => setTimeout(r, 200 * 2 ** attempt));
78
+ }
79
+ }
80
+ throw lastError;
81
+ }
82
+ //#endregion
83
+ //#region src/shared/drain.ts
84
+ /**
85
+ * Build a drain callback. Errors raised by `send` are logged with the drain
86
+ * name and swallowed, so a failing drain never breaks the request pipeline.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * export function createMyDrain(overrides?: Partial<MyConfig>) {
91
+ * return defineDrain<MyConfig>({
92
+ * name: 'my-drain',
93
+ * resolve: () => ({ url: process.env.MY_URL ?? null }),
94
+ * send: async (events, config) => { ... },
95
+ * })
96
+ * }
97
+ * ```
98
+ */
99
+ function defineDrain(options) {
100
+ return async (ctx) => {
101
+ const contexts = Array.isArray(ctx) ? ctx : [ctx];
102
+ if (contexts.length === 0) return;
103
+ const config = await options.resolve();
104
+ if (!config) return;
105
+ try {
106
+ await options.send(contexts.map((c) => c.event), config);
107
+ } catch (error) {
108
+ console.error(`[evlog/${options.name}] Failed to send events:`, error);
109
+ }
110
+ };
111
+ }
112
+ const DEFAULT_HTTP_TIMEOUT = 5e3;
113
+ /**
114
+ * Build an HTTP drain. Timeouts/retries are resolved from the config (with
115
+ * overrides via `resolveTimeout` / `resolveRetries`) and forwarded to
116
+ * {@link httpPost}.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * export function createMyDrain(overrides?: Partial<MyConfig>) {
121
+ * return defineHttpDrain<MyConfig>({
122
+ * name: 'my',
123
+ * resolve: async () => {
124
+ * const cfg = await resolveAdapterConfig<MyConfig>('my', FIELDS, overrides)
125
+ * return cfg.apiKey ? cfg as MyConfig : null
126
+ * },
127
+ * encode: (events, config) => ({
128
+ * url: `${config.endpoint ?? 'https://api.my.com'}/ingest`,
129
+ * headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.apiKey}` },
130
+ * body: JSON.stringify(events),
131
+ * }),
132
+ * })
133
+ * }
134
+ * ```
135
+ */
136
+ function defineHttpDrain(options) {
137
+ return defineDrain({
138
+ name: options.name,
139
+ resolve: options.resolve,
140
+ send: async (events, config) => {
141
+ if (events.length === 0) return;
142
+ const request = options.encode(events, config);
143
+ if (!request) return;
144
+ const timeout = options.resolveTimeout?.(config) ?? config.timeout ?? options.timeout ?? DEFAULT_HTTP_TIMEOUT;
145
+ const retries = options.resolveRetries?.(config) ?? config.retries ?? options.retries;
146
+ await httpPost({
147
+ url: request.url,
148
+ headers: request.headers,
149
+ body: request.body,
150
+ timeout,
151
+ retries,
152
+ label: options.name
153
+ });
154
+ }
155
+ });
156
+ }
157
+ //#endregion
158
+ export { resolveAdapterConfig as a, getRuntimeConfig as i, defineHttpDrain as n, httpPost as r, defineDrain as t };
159
+
160
+ //# sourceMappingURL=drain-ByWUeOQC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drain-ByWUeOQC.mjs","names":[],"sources":["../src/shared/config.ts","../src/shared/http.ts","../src/shared/drain.ts"],"sourcesContent":["import { getNitroRuntimeConfigRecord } from './nitroConfigBridge'\n\n/** Read the full Nitro `useRuntimeConfig()` record (or `undefined` outside Nitro). */\nexport function getRuntimeConfig(): Promise<Record<string, any> | undefined> {\n return getNitroRuntimeConfigRecord()\n}\n\n/**\n * Description of a single adapter config field. `env` is the ordered list of\n * environment variables to fall back to, e.g. `['NUXT_AXIOM_TOKEN', 'AXIOM_TOKEN']`.\n */\nexport interface ConfigField<T> {\n key: keyof T & string\n env?: string[]\n}\n\n/**\n * Resolve adapter configuration with the standard priority chain:\n *\n * 1. `overrides` passed to the drain factory\n * 2. `runtimeConfig.evlog.{namespace}.{key}` (Nitro)\n * 3. `runtimeConfig.{namespace}.{key}` (Nitro)\n * 4. `process.env[envKey]` for each env in `field.env`\n */\nexport async function resolveAdapterConfig<T>(\n namespace: string,\n fields: ConfigField<T>[],\n overrides?: Partial<T>,\n): Promise<Partial<T>> {\n const runtimeConfig = shouldProbeRuntimeConfig(fields, overrides)\n ? await getRuntimeConfig()\n : undefined\n const evlogNs = runtimeConfig?.evlog?.[namespace]\n const rootNs = runtimeConfig?.[namespace]\n\n const config: Record<string, unknown> = {}\n\n for (const { key, env } of fields) {\n config[key] =\n overrides?.[key]\n ?? evlogNs?.[key]\n ?? rootNs?.[key]\n ?? resolveEnv(env)\n }\n\n return config as Partial<T>\n}\n\n// Avoid the Nitro virtual-module import when env/overrides already resolve\n// every env-backed field — optional tuning fields (timeout, retries) should\n// not trigger a runtime probe in non-Nitro runtimes.\nfunction shouldProbeRuntimeConfig<T>(\n fields: ConfigField<T>[],\n overrides?: Partial<T>,\n): boolean {\n return fields.some(({ key, env }) => {\n if (overrides?.[key] !== undefined) return false\n if (!env) return false\n return resolveEnv(env) === undefined\n })\n}\n\nfunction resolveEnv(envKeys?: string[]): string | undefined {\n if (!envKeys) return undefined\n for (const key of envKeys) {\n const val = process.env[key]\n if (val) return val\n }\n return undefined\n}\n","/**\n * Minimal HTTP transport for drain adapters: abort-based timeouts, exponential\n * backoff on `5xx` / network errors, response bodies truncated in error messages.\n */\n\nexport interface HttpPostOptions {\n url: string\n /** Caller is responsible for `Content-Type`. */\n headers: Record<string, string>\n /** Pre-serialized request body. */\n body: string\n /** Abort the request after this many milliseconds. */\n timeout: number\n /** Prefix used in error messages. */\n label: string\n /**\n * Retries network errors, aborts, and `5xx` responses with exponential backoff.\n * @default 2\n */\n retries?: number\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof DOMException && error.name === 'AbortError') return true\n if (error instanceof TypeError) return true\n if (error instanceof Error) {\n const match = error.message.match(/API error: (\\d+)/)\n if (match) return Number.parseInt(match[1]) >= 500\n }\n return false\n}\n\n/**\n * POST a body with timeout + retry. Throws label-prefixed errors with a\n * truncated response body. Safe to call from any drain `send()`.\n */\nexport async function httpPost({ url, headers, body, timeout, label, retries = 2 }: HttpPostOptions): Promise<void> {\n const normalizedRetries = Number.isFinite(retries) && retries >= 0 ? Math.floor(retries) : 2\n\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= normalizedRetries; attempt++) {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body,\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const text = await response.text().catch(() => 'Unknown error')\n const safeText = text.length > 200 ? `${text.slice(0, 200)}...[truncated]` : text\n throw new Error(`${label} API error: ${response.status} ${response.statusText} - ${safeText}`)\n }\n\n clearTimeout(timeoutId)\n return\n } catch (error) {\n clearTimeout(timeoutId)\n\n if (error instanceof DOMException && error.name === 'AbortError') {\n lastError = new Error(`${label} request timed out after ${timeout}ms`)\n } else {\n lastError = error as Error\n }\n\n if (!isRetryable(error) || attempt === normalizedRetries) {\n throw lastError\n }\n\n await new Promise<void>(r => setTimeout(r, 200 * 2 ** attempt))\n }\n }\n\n throw lastError!\n}\n","import type { DrainContext, WideEvent } from '../types'\nimport { httpPost } from './http'\n\n/**\n * Drain definition backed by an arbitrary `send` function. Use this for\n * non-HTTP transports (filesystem, in-memory queue, native SDK). For HTTP\n * backends, use `defineHttpDrain` instead.\n */\nexport interface DrainOptions<TConfig> {\n /** Stable identifier used in error logs. */\n name: string\n /** Return `null` to skip draining (e.g. missing API key in dev). */\n resolve: () => TConfig | null | Promise<TConfig | null>\n send: (events: WideEvent[], config: TConfig) => Promise<void>\n}\n\n/**\n * Build a drain callback. Errors raised by `send` are logged with the drain\n * name and swallowed, so a failing drain never breaks the request pipeline.\n *\n * @example\n * ```ts\n * export function createMyDrain(overrides?: Partial<MyConfig>) {\n * return defineDrain<MyConfig>({\n * name: 'my-drain',\n * resolve: () => ({ url: process.env.MY_URL ?? null }),\n * send: async (events, config) => { ... },\n * })\n * }\n * ```\n */\nexport function defineDrain<TConfig>(options: DrainOptions<TConfig>): (ctx: DrainContext | DrainContext[]) => Promise<void> {\n return async (ctx: DrainContext | DrainContext[]) => {\n const contexts = Array.isArray(ctx) ? ctx : [ctx]\n if (contexts.length === 0) return\n\n const config = await options.resolve()\n if (!config) return\n\n try {\n await options.send(contexts.map(c => c.event), config)\n } catch (error) {\n console.error(`[evlog/${options.name}] Failed to send events:`, error)\n }\n }\n}\n\nexport interface HttpDrainRequest {\n url: string\n /** Caller is responsible for `Content-Type`. */\n headers: Record<string, string>\n body: string\n}\n\n/** Adapters only need to ship config + `encode()` — no manual `fetch`. */\nexport interface HttpDrainOptions<TConfig> {\n /** Stable identifier used in error logs. */\n name: string\n /** Return `null` to skip draining (e.g. missing API key in dev). */\n resolve: () => TConfig | null | Promise<TConfig | null>\n /** Return `null` to skip the batch without raising. */\n encode: (events: WideEvent[], config: TConfig) => HttpDrainRequest | null\n /** @default 5000 */\n timeout?: number\n /** @default 2 */\n retries?: number\n /** Read the timeout off the resolved config (falls back to `timeout`). */\n resolveTimeout?: (config: TConfig) => number | undefined\n /** Read the retry count off the resolved config (falls back to `retries`). */\n resolveRetries?: (config: TConfig) => number | undefined\n}\n\nconst DEFAULT_HTTP_TIMEOUT = 5000\n\n/**\n * Build an HTTP drain. Timeouts/retries are resolved from the config (with\n * overrides via `resolveTimeout` / `resolveRetries`) and forwarded to\n * {@link httpPost}.\n *\n * @example\n * ```ts\n * export function createMyDrain(overrides?: Partial<MyConfig>) {\n * return defineHttpDrain<MyConfig>({\n * name: 'my',\n * resolve: async () => {\n * const cfg = await resolveAdapterConfig<MyConfig>('my', FIELDS, overrides)\n * return cfg.apiKey ? cfg as MyConfig : null\n * },\n * encode: (events, config) => ({\n * url: `${config.endpoint ?? 'https://api.my.com'}/ingest`,\n * headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.apiKey}` },\n * body: JSON.stringify(events),\n * }),\n * })\n * }\n * ```\n */\nexport function defineHttpDrain<TConfig>(options: HttpDrainOptions<TConfig>): (ctx: DrainContext | DrainContext[]) => Promise<void> {\n return defineDrain<TConfig>({\n name: options.name,\n resolve: options.resolve,\n send: async (events, config) => {\n if (events.length === 0) return\n const request = options.encode(events, config)\n if (!request) return\n const timeout = options.resolveTimeout?.(config)\n ?? (config as { timeout?: number }).timeout\n ?? options.timeout\n ?? DEFAULT_HTTP_TIMEOUT\n const retries = options.resolveRetries?.(config)\n ?? (config as { retries?: number }).retries\n ?? options.retries\n await httpPost({\n url: request.url,\n headers: request.headers,\n body: request.body,\n timeout,\n retries,\n label: options.name,\n })\n },\n })\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { Y as RequestLogger } from "../audit-CTIviX3P.mjs";
2
- import { t as BaseEvlogOptions } from "../middleware-CTnDsST-.mjs";
1
+ import { Y as RequestLogger } from "../audit-X1uUukm3.mjs";
2
+ import { t as BaseEvlogOptions } from "../middleware-CAQHJRN1.mjs";
3
3
  import { Elysia } from "elysia";
4
4
 
5
5
  //#region src/elysia/index.d.ts
@@ -23,6 +23,29 @@ type EvlogElysiaOptions = BaseEvlogOptions;
23
23
  * ```
24
24
  */
25
25
  declare function useLogger<T extends object = Record<string, unknown>>(): RequestLogger<T>;
26
+ /**
27
+ * Create an evlog plugin for Elysia.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * import { Elysia } from 'elysia'
32
+ * import { evlog } from 'evlog/elysia'
33
+ * import { createAxiomDrain } from 'evlog/axiom'
34
+ *
35
+ * const app = new Elysia()
36
+ * .use(evlog({
37
+ * drain: createAxiomDrain(),
38
+ * enrich: (ctx) => {
39
+ * ctx.event.region = process.env.FLY_REGION
40
+ * },
41
+ * }))
42
+ * .get('/health', ({ log }) => {
43
+ * log.set({ route: 'health' })
44
+ * return { ok: true }
45
+ * })
46
+ * .listen(3000)
47
+ * ```
48
+ */
26
49
  declare function evlog(options?: EvlogElysiaOptions): Elysia<"", {
27
50
  decorator: {};
28
51
  store: {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/elysia/index.ts"],"mappings":";;;;;KAgBY,kBAAA,GAAqB,gBAAA;;AAAjC;;;;;AAoBA;;;;;;;;;;;;iBAAgB,SAAA,oBAA6B,MAAA,kBAAA,CAAA,GAA4B,aAAA,CAAc,CAAA;AAAA,iBAwCvE,KAAA,CAAM,OAAA,GAAS,kBAAA,GAAuB,MAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/elysia/index.ts"],"mappings":";;;;;KAWY,kBAAA,GAAqB,gBAAA;;AAAjC;;;;;AAoBA;;;;;;;;;;;;iBAAgB,SAAA,oBAA6B,MAAA,kBAAA,CAAA,GAA4B,aAAA,CAAc,CAAA;;AAuEvF;;;;;;;;;;;;;;;;;;;;;;iBAAgB,KAAA,CAAM,OAAA,GAAS,kBAAA,GAAuB,MAAA"}
@@ -1,6 +1,5 @@
1
- import { filterSafeHeaders } from "../utils.mjs";
2
- import { t as createMiddlewareLogger } from "../middleware-oAccqyPp.mjs";
3
- import { t as attachForkToLogger } from "../fork-D1j1Fuzy.mjs";
1
+ import { t as attachForkToLogger } from "../fork-DPN8aL8O.mjs";
2
+ import { t as defineFrameworkIntegration } from "../integration-DSZPbI9N.mjs";
4
3
  import { AsyncLocalStorage } from "node:async_hooks";
5
4
  import { Elysia } from "elysia";
6
5
  //#region src/elysia/index.ts
@@ -29,29 +28,63 @@ function useLogger() {
29
28
  if (!logger || !activeLoggers.has(logger)) throw new Error("[evlog] useLogger() was called outside of an evlog plugin context. Make sure app.use(evlog()) is registered before your routes.");
30
29
  return logger;
31
30
  }
31
+ const integration = defineFrameworkIntegration({
32
+ name: "elysia",
33
+ extractRequest: ({ request, path, headers }) => ({
34
+ method: request.method,
35
+ path,
36
+ headers,
37
+ requestId: headers["x-request-id"]
38
+ }),
39
+ attachLogger: ({ request, path, headers }, logger) => {
40
+ attachForkToLogger(storage, logger, {
41
+ method: request.method,
42
+ path,
43
+ requestId: headers["x-request-id"]
44
+ }, {
45
+ onChildEnter: (child) => {
46
+ activeLoggers.add(child);
47
+ },
48
+ onChildExit: (child) => {
49
+ activeLoggers.delete(child);
50
+ }
51
+ });
52
+ activeLoggers.add(logger);
53
+ }
54
+ });
55
+ /**
56
+ * Create an evlog plugin for Elysia.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * import { Elysia } from 'elysia'
61
+ * import { evlog } from 'evlog/elysia'
62
+ * import { createAxiomDrain } from 'evlog/axiom'
63
+ *
64
+ * const app = new Elysia()
65
+ * .use(evlog({
66
+ * drain: createAxiomDrain(),
67
+ * enrich: (ctx) => {
68
+ * ctx.event.region = process.env.FLY_REGION
69
+ * },
70
+ * }))
71
+ * .get('/health', ({ log }) => {
72
+ * log.set({ route: 'health' })
73
+ * return { ok: true }
74
+ * })
75
+ * .listen(3000)
76
+ * ```
77
+ */
32
78
  function evlog(options = {}) {
33
79
  const emitted = /* @__PURE__ */ new WeakSet();
34
80
  const requestState = /* @__PURE__ */ new WeakMap();
35
81
  return new Elysia({ name: "evlog" }).derive({ as: "global" }, ({ request, path, headers }) => {
36
- const middlewareOpts = {
37
- method: request.method,
82
+ const ctx = {
83
+ request,
38
84
  path,
39
- requestId: headers["x-request-id"] || crypto.randomUUID(),
40
- headers: filterSafeHeaders(headers),
41
- ...options
85
+ headers
42
86
  };
43
- const { logger, finish, skipped } = createMiddlewareLogger(middlewareOpts);
44
- if (!skipped) {
45
- attachForkToLogger(storage, logger, middlewareOpts, {
46
- onChildEnter: (child) => {
47
- activeLoggers.add(child);
48
- },
49
- onChildExit: (child) => {
50
- activeLoggers.delete(child);
51
- }
52
- });
53
- activeLoggers.add(logger);
54
- }
87
+ const { logger, finish, skipped } = integration.start(ctx, options);
55
88
  storage.enterWith(logger);
56
89
  requestState.set(request, {
57
90
  finish,
@@ -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 { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { filterSafeHeaders } from '../utils'\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, path, headers }) => {\n const middlewareOpts = {\n method: request.method,\n path,\n requestId: headers['x-request-id'] || crypto.randomUUID(),\n // It's recommended to use context.headers instead of context.request.headers\n // because Elysia has fast path for getting headers on Bun\n headers: filterSafeHeaders(headers as Record<string, string>),\n ...options,\n }\n const { logger, finish, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (!skipped) {\n attachForkToLogger(storage, logger, middlewareOpts, {\n onChildEnter: (child) => {\n activeLoggers.add(child)\n },\n onChildExit: (child) => {\n activeLoggers.delete(child)\n },\n })\n activeLoggers.add(logger)\n }\n storage.enterWith(logger)\n requestState.set(request, { finish, skipped, logger })\n\n return { log: logger }\n })\n .onAfterResponse({ 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":";;;;;;AAQA,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,SAAS,MAAM,cAAc;EACxD,MAAM,iBAAiB;GACrB,QAAQ,QAAQ;GAChB;GACA,WAAW,QAAQ,mBAAmB,OAAO,YAAY;GAGzD,SAAS,kBAAkB,QAAkC;GAC7D,GAAG;GACJ;EACD,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB,eAAe;AAE1E,MAAI,CAAC,SAAS;AACZ,sBAAmB,SAAS,QAAQ,gBAAgB;IAClD,eAAe,UAAU;AACvB,mBAAc,IAAI,MAAM;;IAE1B,cAAc,UAAU;AACtB,mBAAc,OAAO,MAAM;;IAE9B,CAAC;AACF,iBAAc,IAAI,OAAO;;AAE3B,UAAQ,UAAU,OAAO;AACzB,eAAa,IAAI,SAAS;GAAE;GAAQ;GAAS;GAAQ,CAAC;AAEtD,SAAO,EAAE,KAAK,QAAQ;GACtB,CACD,gBAAgB,EAAE,IAAI,UAAU,EAAE,OAAO,EAAE,SAAS,UAAU;EAC7D,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
+ {"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 { defineFrameworkIntegration } from '../shared/integration'\nimport type { BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\n\nconst storage = new AsyncLocalStorage<RequestLogger>()\n\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\ninterface ElysiaContext {\n request: Request\n path: string\n headers: Record<string, string>\n}\n\nconst integration = defineFrameworkIntegration<ElysiaContext>({\n name: 'elysia',\n extractRequest: ({ request, path, headers }) => ({\n method: request.method,\n path,\n headers,\n requestId: headers['x-request-id'],\n }),\n attachLogger: ({ request, path, headers }, logger) => {\n attachForkToLogger(storage, logger, {\n method: request.method,\n path,\n requestId: headers['x-request-id'],\n }, {\n onChildEnter: (child) => {\n activeLoggers.add(child)\n },\n onChildExit: (child) => {\n activeLoggers.delete(child)\n },\n })\n activeLoggers.add(logger)\n },\n})\n\ninterface RequestState {\n finish: (opts?: { status?: number; error?: Error }) => Promise<unknown>\n skipped: boolean\n logger: RequestLogger\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 */\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, path, headers }) => {\n const ctx: ElysiaContext = { request, path, headers: headers as Record<string, string> }\n const { logger, finish, skipped } = integration.start(ctx, options)\n storage.enterWith(logger)\n requestState.set(request, { finish, skipped, logger })\n return { log: logger }\n })\n .onAfterResponse({ 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":";;;;;AAOA,MAAM,UAAU,IAAI,mBAAkC;AAEtD,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;;AAST,MAAM,cAAc,2BAA0C;CAC5D,MAAM;CACN,iBAAiB,EAAE,SAAS,MAAM,eAAe;EAC/C,QAAQ,QAAQ;EAChB;EACA;EACA,WAAW,QAAQ;EACpB;CACD,eAAe,EAAE,SAAS,MAAM,WAAW,WAAW;AACpD,qBAAmB,SAAS,QAAQ;GAClC,QAAQ,QAAQ;GAChB;GACA,WAAW,QAAQ;GACpB,EAAE;GACD,eAAe,UAAU;AACvB,kBAAc,IAAI,MAAM;;GAE1B,cAAc,UAAU;AACtB,kBAAc,OAAO,MAAM;;GAE9B,CAAC;AACF,gBAAc,IAAI,OAAO;;CAE5B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AA+BF,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,SAAS,MAAM,cAAc;EACxD,MAAM,MAAqB;GAAE;GAAS;GAAe;GAAmC;EACxF,MAAM,EAAE,QAAQ,QAAQ,YAAY,YAAY,MAAM,KAAK,QAAQ;AACnE,UAAQ,UAAU,OAAO;AACzB,eAAa,IAAI,SAAS;GAAE;GAAQ;GAAS;GAAQ,CAAC;AACtD,SAAO,EAAE,KAAK,QAAQ;GACtB,CACD,gBAAgB,EAAE,IAAI,UAAU,EAAE,OAAO,EAAE,SAAS,UAAU;EAC7D,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"}
@@ -0,0 +1,42 @@
1
+ import { I as EnrichContext, it as WideEvent } from "./audit-X1uUukm3.mjs";
2
+
3
+ //#region src/shared/enricher.d.ts
4
+ interface EnricherOptions {
5
+ /**
6
+ * Replace existing event fields with the computed value. Defaults to `false`
7
+ * so user-provided context (e.g. `log.set({ geo: ... })`) wins.
8
+ */
9
+ overwrite?: boolean;
10
+ }
11
+ interface EnricherDefinition<T> {
12
+ /** Stable identifier used in error logs. */
13
+ name: string;
14
+ /**
15
+ * Top-level event field to merge into. Omit when the enricher writes to
16
+ * multiple fields and handles its own merging inside `compute`.
17
+ */
18
+ field?: keyof WideEvent & string;
19
+ /** Return `undefined` to skip enrichment (e.g. when a required header is missing). */
20
+ compute: (ctx: EnrichContext) => T | undefined;
21
+ }
22
+ /**
23
+ * Build an enricher: skips when `compute` returns `undefined`, merges with
24
+ * {@link mergeEventField} respecting `overwrite`, and isolates errors under
25
+ * `[evlog/{name}]`.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * export const tenantEnricher = defineEnricher<{ id: string }>({
30
+ * name: 'tenant',
31
+ * field: 'tenant',
32
+ * compute({ headers }) {
33
+ * const id = getHeader(headers, 'x-tenant-id')
34
+ * return id ? { id } : undefined
35
+ * },
36
+ * })
37
+ * ```
38
+ */
39
+ declare function defineEnricher<T>(def: EnricherDefinition<T>, options?: EnricherOptions): (ctx: EnrichContext) => void;
40
+ //#endregion
41
+ export { EnricherOptions as n, defineEnricher as r, EnricherDefinition as t };
42
+ //# sourceMappingURL=enricher-DYTr9I16.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enricher-DYTr9I16.d.mts","names":[],"sources":["../src/shared/enricher.ts"],"mappings":";;;UAGiB,eAAA;;AAAjB;;;EAKE,SAAA;AAAA;AAAA,UAGe,kBAAA;EAAkB;EAEjC,IAAA;EAKc;;;;EAAd,KAAA,SAAc,SAAA;EAPoB;EASlC,OAAA,GAAU,GAAA,EAAK,aAAA,KAAkB,CAAA;AAAA;;;;;;;;AAoBnC;;;;;;;;;;iBAAgB,cAAA,GAAA,CACd,GAAA,EAAK,kBAAA,CAAmB,CAAA,GACxB,OAAA,GAAS,eAAA,IACP,GAAA,EAAK,aAAA"}
@@ -0,0 +1,95 @@
1
+ import { t as mergeEventField } from "./event-DcHmEm3O.mjs";
2
+ //#region src/shared/compose.ts
3
+ /**
4
+ * Compose enricher callbacks into one. Runs in registration order; errors are
5
+ * caught per-callback so one buggy enricher never blocks the others.
6
+ */
7
+ function composeEnrichers(enrichers, options = {}) {
8
+ const label = options.name ?? "compose-enrichers";
9
+ return async (ctx) => {
10
+ for (const enricher of enrichers) try {
11
+ await enricher(ctx);
12
+ } catch (err) {
13
+ console.error(`[evlog/${label}] enrich failed:`, err);
14
+ }
15
+ };
16
+ }
17
+ /**
18
+ * Fan out to multiple drains concurrently (`Promise.allSettled`). A slow
19
+ * Sentry drain never blocks an Axiom drain on the same event.
20
+ */
21
+ function composeDrains(drains, options = {}) {
22
+ const label = options.name ?? "compose-drains";
23
+ return async (ctx) => {
24
+ if (drains.length === 0) return;
25
+ await Promise.allSettled(drains.map(async (drain) => {
26
+ try {
27
+ await drain(ctx);
28
+ } catch (err) {
29
+ console.error(`[evlog/${label}] drain failed:`, err);
30
+ }
31
+ }));
32
+ };
33
+ }
34
+ /**
35
+ * Compose tail-sampling `keep` callbacks. `ctx.shouldKeep` is true after the
36
+ * run if any callback set it. Errors are isolated.
37
+ */
38
+ function composeKeep(keepers, options = {}) {
39
+ const label = options.name ?? "compose-keep";
40
+ return async (ctx) => {
41
+ for (const keep of keepers) try {
42
+ await keep(ctx);
43
+ } catch (err) {
44
+ console.error(`[evlog/${label}] keep failed:`, err);
45
+ }
46
+ };
47
+ }
48
+ /** Merge plugin lists. Later registrations override earlier ones by `name`. */
49
+ function composePlugins(...lists) {
50
+ const merged = /* @__PURE__ */ new Map();
51
+ for (const list of lists) {
52
+ if (!list) continue;
53
+ for (const plugin of list) merged.set(plugin.name, plugin);
54
+ }
55
+ return Array.from(merged.values());
56
+ }
57
+ //#endregion
58
+ //#region src/shared/enricher.ts
59
+ /**
60
+ * Build an enricher: skips when `compute` returns `undefined`, merges with
61
+ * {@link mergeEventField} respecting `overwrite`, and isolates errors under
62
+ * `[evlog/{name}]`.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * export const tenantEnricher = defineEnricher<{ id: string }>({
67
+ * name: 'tenant',
68
+ * field: 'tenant',
69
+ * compute({ headers }) {
70
+ * const id = getHeader(headers, 'x-tenant-id')
71
+ * return id ? { id } : undefined
72
+ * },
73
+ * })
74
+ * ```
75
+ */
76
+ function defineEnricher(def, options = {}) {
77
+ const { name, field, compute } = def;
78
+ return (ctx) => {
79
+ let computed;
80
+ try {
81
+ computed = compute(ctx);
82
+ } catch (err) {
83
+ console.error(`[evlog/${name}] enrich failed:`, err);
84
+ return;
85
+ }
86
+ if (computed === void 0) return;
87
+ if (!field) return;
88
+ const target = ctx.event[field];
89
+ ctx.event[field] = mergeEventField(target, computed, options.overwrite);
90
+ };
91
+ }
92
+ //#endregion
93
+ export { composePlugins as a, composeKeep as i, composeDrains as n, composeEnrichers as r, defineEnricher as t };
94
+
95
+ //# sourceMappingURL=enricher-Dy06T17G.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enricher-Dy06T17G.mjs","names":[],"sources":["../src/shared/compose.ts","../src/shared/enricher.ts"],"sourcesContent":["import type { DrainContext, EnrichContext, TailSamplingContext } from '../types'\nimport type { EvlogPlugin } from './plugin'\n\n/**\n * Compose enricher callbacks into one. Runs in registration order; errors are\n * caught per-callback so one buggy enricher never blocks the others.\n */\nexport function composeEnrichers(\n enrichers: Array<(ctx: EnrichContext) => void | Promise<void>>,\n options: { name?: string } = {},\n): (ctx: EnrichContext) => Promise<void> {\n const label = options.name ?? 'compose-enrichers'\n return async (ctx) => {\n for (const enricher of enrichers) {\n try {\n await enricher(ctx)\n } catch (err) {\n console.error(`[evlog/${label}] enrich failed:`, err)\n }\n }\n }\n}\n\n/**\n * Fan out to multiple drains concurrently (`Promise.allSettled`). A slow\n * Sentry drain never blocks an Axiom drain on the same event.\n */\nexport function composeDrains(\n drains: Array<(ctx: DrainContext) => void | Promise<void>>,\n options: { name?: string } = {},\n): (ctx: DrainContext) => Promise<void> {\n const label = options.name ?? 'compose-drains'\n return async (ctx) => {\n if (drains.length === 0) return\n await Promise.allSettled(\n drains.map(async (drain) => {\n try {\n await drain(ctx)\n } catch (err) {\n console.error(`[evlog/${label}] drain failed:`, err)\n }\n }),\n )\n }\n}\n\n/**\n * Compose tail-sampling `keep` callbacks. `ctx.shouldKeep` is true after the\n * run if any callback set it. Errors are isolated.\n */\nexport function composeKeep(\n keepers: Array<(ctx: TailSamplingContext) => void | Promise<void>>,\n options: { name?: string } = {},\n): (ctx: TailSamplingContext) => Promise<void> {\n const label = options.name ?? 'compose-keep'\n return async (ctx) => {\n for (const keep of keepers) {\n try {\n await keep(ctx)\n } catch (err) {\n console.error(`[evlog/${label}] keep failed:`, err)\n }\n }\n }\n}\n\n/** Merge plugin lists. Later registrations override earlier ones by `name`. */\nexport function composePlugins(...lists: Array<EvlogPlugin[] | undefined>): EvlogPlugin[] {\n const merged = new Map<string, EvlogPlugin>()\n for (const list of lists) {\n if (!list) continue\n for (const plugin of list) {\n merged.set(plugin.name, plugin)\n }\n }\n return Array.from(merged.values())\n}\n","import type { EnrichContext, WideEvent } from '../types'\nimport { mergeEventField } from './event'\n\nexport interface EnricherOptions {\n /**\n * Replace existing event fields with the computed value. Defaults to `false`\n * so user-provided context (e.g. `log.set({ geo: ... })`) wins.\n */\n overwrite?: boolean\n}\n\nexport interface EnricherDefinition<T> {\n /** Stable identifier used in error logs. */\n name: string\n /**\n * Top-level event field to merge into. Omit when the enricher writes to\n * multiple fields and handles its own merging inside `compute`.\n */\n field?: keyof WideEvent & string\n /** Return `undefined` to skip enrichment (e.g. when a required header is missing). */\n compute: (ctx: EnrichContext) => T | undefined\n}\n\n/**\n * Build an enricher: skips when `compute` returns `undefined`, merges with\n * {@link mergeEventField} respecting `overwrite`, and isolates errors under\n * `[evlog/{name}]`.\n *\n * @example\n * ```ts\n * export const tenantEnricher = defineEnricher<{ id: string }>({\n * name: 'tenant',\n * field: 'tenant',\n * compute({ headers }) {\n * const id = getHeader(headers, 'x-tenant-id')\n * return id ? { id } : undefined\n * },\n * })\n * ```\n */\nexport function defineEnricher<T>(\n def: EnricherDefinition<T>,\n options: EnricherOptions = {},\n): (ctx: EnrichContext) => void {\n const { name, field, compute } = def\n return (ctx) => {\n let computed: T | undefined\n try {\n computed = compute(ctx)\n } catch (err) {\n console.error(`[evlog/${name}] enrich failed:`, err)\n return\n }\n if (computed === undefined) return\n if (!field) return\n const target = ctx.event[field]\n ctx.event[field] = mergeEventField<T>(target, computed, options.overwrite)\n }\n}\n"],"mappings":";;;;;;AAOA,SAAgB,iBACd,WACA,UAA6B,EAAE,EACQ;CACvC,MAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAO,OAAO,QAAQ;AACpB,OAAK,MAAM,YAAY,UACrB,KAAI;AACF,SAAM,SAAS,IAAI;WACZ,KAAK;AACZ,WAAQ,MAAM,UAAU,MAAM,mBAAmB,IAAI;;;;;;;;AAU7D,SAAgB,cACd,QACA,UAA6B,EAAE,EACO;CACtC,MAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAO,OAAO,QAAQ;AACpB,MAAI,OAAO,WAAW,EAAG;AACzB,QAAM,QAAQ,WACZ,OAAO,IAAI,OAAO,UAAU;AAC1B,OAAI;AACF,UAAM,MAAM,IAAI;YACT,KAAK;AACZ,YAAQ,MAAM,UAAU,MAAM,kBAAkB,IAAI;;IAEtD,CACH;;;;;;;AAQL,SAAgB,YACd,SACA,UAA6B,EAAE,EACc;CAC7C,MAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAO,OAAO,QAAQ;AACpB,OAAK,MAAM,QAAQ,QACjB,KAAI;AACF,SAAM,KAAK,IAAI;WACR,KAAK;AACZ,WAAQ,MAAM,UAAU,MAAM,iBAAiB,IAAI;;;;;AAO3D,SAAgB,eAAe,GAAG,OAAwD;CACxF,MAAM,yBAAS,IAAI,KAA0B;AAC7C,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,KAAM;AACX,OAAK,MAAM,UAAU,KACnB,QAAO,IAAI,OAAO,MAAM,OAAO;;AAGnC,QAAO,MAAM,KAAK,OAAO,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;ACnCpC,SAAgB,eACd,KACA,UAA2B,EAAE,EACC;CAC9B,MAAM,EAAE,MAAM,OAAO,YAAY;AACjC,SAAQ,QAAQ;EACd,IAAI;AACJ,MAAI;AACF,cAAW,QAAQ,IAAI;WAChB,KAAK;AACZ,WAAQ,MAAM,UAAU,KAAK,mBAAmB,IAAI;AACpD;;AAEF,MAAI,aAAa,KAAA,EAAW;AAC5B,MAAI,CAAC,MAAO;EACZ,MAAM,SAAS,IAAI,MAAM;AACzB,MAAI,MAAM,SAAS,gBAAmB,QAAQ,UAAU,QAAQ,UAAU"}
@@ -1,13 +1,7 @@
1
- import { I as EnrichContext } from "./audit-CTIviX3P.mjs";
1
+ import { I as EnrichContext } from "./audit-X1uUukm3.mjs";
2
+ import { n as EnricherOptions } from "./enricher-DYTr9I16.mjs";
2
3
 
3
4
  //#region src/enrichers/index.d.ts
4
- interface EnricherOptions {
5
- /**
6
- * When true, overwrite any existing fields in the event.
7
- * Defaults to false to preserve user-provided data.
8
- */
9
- overwrite?: boolean;
10
- }
11
5
  interface UserAgentInfo {
12
6
  raw: string;
13
7
  browser?: {
@@ -69,6 +63,19 @@ declare function createRequestSizeEnricher(options?: EnricherOptions): (ctx: Enr
69
63
  * Also sets `event.traceId` and `event.spanId` at the top level.
70
64
  */
71
65
  declare function createTraceContextEnricher(options?: EnricherOptions): (ctx: EnrichContext) => void;
66
+ /**
67
+ * Compose every built-in enricher into a single async enricher, in the order
68
+ * `userAgent → geo → requestSize → traceContext`.
69
+ *
70
+ * Drop-in shorthand for the most common middleware setup:
71
+ *
72
+ * ```ts
73
+ * import { createDefaultEnrichers } from 'evlog/enrichers'
74
+ *
75
+ * app.use(evlog({ enrich: createDefaultEnrichers() }))
76
+ * ```
77
+ */
78
+ declare function createDefaultEnrichers(options?: EnricherOptions): (ctx: EnrichContext) => Promise<void>;
72
79
  //#endregion
73
- export { EnricherOptions, GeoInfo, RequestSizeInfo, TraceContextInfo, UserAgentInfo, createGeoEnricher, createRequestSizeEnricher, createTraceContextEnricher, createUserAgentEnricher };
80
+ export { type EnricherOptions, GeoInfo, RequestSizeInfo, TraceContextInfo, UserAgentInfo, createDefaultEnrichers, createGeoEnricher, createRequestSizeEnricher, createTraceContextEnricher, createUserAgentEnricher };
74
81
  //# sourceMappingURL=enrichers.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"enrichers.d.mts","names":[],"sources":["../src/enrichers/index.ts"],"mappings":";;;UAEiB,eAAA;;AAAjB;;;EAKE,SAAA;AAAA;AAAA,UAGe,aAAA;EACf,GAAA;EACA,OAAA;IAAY,IAAA;IAAc,OAAA;EAAA;EAC1B,EAAA;IAAO,IAAA;IAAc,OAAA;EAAA;EACrB,MAAA;IAAW,IAAA;EAAA;AAAA;AAAA,UAGI,OAAA;EACf,OAAA;EACA,MAAA;EACA,UAAA;EACA,IAAA;EACA,QAAA;EACA,SAAA;AAAA;AAAA,UAGe,eAAA;EACf,YAAA;EACA,aAAA;AAAA;AAAA,UAGe,gBAAA;EACf,WAAA;EACA,UAAA;EACA,OAAA;EACA,MAAA;AAAA;AAJF;;;;AAAA,iBAoGgB,uBAAA,CAAwB,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA;;;;;;AAA9E;;;;;;;iBAqBgB,iBAAA,CAAkB,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA;;;AAAxE;;iBAuBgB,yBAAA,CAA0B,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA;;;;;;iBAoBhE,0BAAA,CAA2B,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA"}
1
+ {"version":3,"file":"enrichers.d.mts","names":[],"sources":["../src/enrichers/index.ts"],"mappings":";;;;UAOiB,aAAA;EACf,GAAA;EACA,OAAA;IAAY,IAAA;IAAc,OAAA;EAAA;EAC1B,EAAA;IAAO,IAAA;IAAc,OAAA;EAAA;EACrB,MAAA;IAAW,IAAA;EAAA;AAAA;AAAA,UAGI,OAAA;EACf,OAAA;EACA,MAAA;EACA,UAAA;EACA,IAAA;EACA,QAAA;EACA,SAAA;AAAA;AAAA,UAGe,eAAA;EACf,YAAA;EACA,aAAA;AAAA;AAAA,UAGe,gBAAA;EACf,WAAA;EACA,UAAA;EACA,OAAA;EACA,MAAA;AAAA;;AAJF;;;iBAwEgB,uBAAA,CAAwB,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA;;;;;;;AAA9E;;;;;;iBAuBgB,iBAAA,CAAkB,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA;;;;AAAxE;iBAuBgB,yBAAA,CAA0B,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA;;;;;;iBAkBhE,0BAAA,CAA2B,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA;;;AAlBjF;;;;;;;;;;iBA+DgB,sBAAA,CAAuB,OAAA,GAAS,eAAA,IAAwB,GAAA,EAAK,aAAA,KAAkB,OAAA"}