evlog 2.17.0 → 2.18.1

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 (150) hide show
  1. package/README.md +95 -2
  2. package/dist/adapters/axiom.d.mts +1 -1
  3. package/dist/adapters/axiom.mjs +2 -2
  4. package/dist/adapters/axiom.mjs.map +1 -1
  5. package/dist/adapters/better-stack.d.mts +1 -1
  6. package/dist/adapters/better-stack.mjs +2 -2
  7. package/dist/adapters/datadog.d.mts +1 -1
  8. package/dist/adapters/datadog.mjs +2 -2
  9. package/dist/adapters/fs.d.mts +1 -1
  10. package/dist/adapters/fs.mjs +1 -1
  11. package/dist/adapters/hyperdx.d.mts +1 -1
  12. package/dist/adapters/hyperdx.mjs +1 -1
  13. package/dist/adapters/memory.d.mts +116 -0
  14. package/dist/adapters/memory.d.mts.map +1 -0
  15. package/dist/adapters/memory.mjs +191 -0
  16. package/dist/adapters/memory.mjs.map +1 -0
  17. package/dist/adapters/otlp.d.mts +1 -1
  18. package/dist/adapters/otlp.mjs +2 -2
  19. package/dist/adapters/posthog.d.mts +1 -1
  20. package/dist/adapters/posthog.mjs +2 -2
  21. package/dist/adapters/sentry.d.mts +1 -1
  22. package/dist/adapters/sentry.mjs +2 -2
  23. package/dist/ai/index.d.mts +1 -1
  24. package/dist/{audit-pV5aLGP0.mjs → audit-BUI3af4w.mjs} +121 -53
  25. package/dist/audit-BUI3af4w.mjs.map +1 -0
  26. package/dist/{audit-CC8nfazi.d.mts → audit-DVdkntSO.d.mts} +21 -1
  27. package/dist/audit-DVdkntSO.d.mts.map +1 -0
  28. package/dist/better-auth/index.d.mts +1 -1
  29. package/dist/browser.d.mts +1 -1
  30. package/dist/{define-MSdhzmXn.d.mts → define-D-BVMf2l.d.mts} +3 -3
  31. package/dist/{define-MSdhzmXn.d.mts.map → define-D-BVMf2l.d.mts.map} +1 -1
  32. package/dist/define-D6OJdSUH.mjs.map +1 -1
  33. package/dist/{drain-X7_5szSI.mjs → drain-7n3K6kPe.mjs} +3 -3
  34. package/dist/drain-7n3K6kPe.mjs.map +1 -0
  35. package/dist/elysia/index.d.mts +2 -2
  36. package/dist/elysia/index.mjs +2 -2
  37. package/dist/{enricher-DxgML6IC.d.mts → enricher-UW9npoB2.d.mts} +2 -2
  38. package/dist/{enricher-DxgML6IC.d.mts.map → enricher-UW9npoB2.d.mts.map} +1 -1
  39. package/dist/enrichers.d.mts +2 -2
  40. package/dist/{error-CpbbtyXL.d.mts → error-CVtn5U7b.d.mts} +2 -2
  41. package/dist/{error-CpbbtyXL.d.mts.map → error-CVtn5U7b.d.mts.map} +1 -1
  42. package/dist/error.d.mts +1 -1
  43. package/dist/{errors-DySW1F9_.d.mts → errors-dEMNQCiL.d.mts} +2 -2
  44. package/dist/{errors-DySW1F9_.d.mts.map → errors-dEMNQCiL.d.mts.map} +1 -1
  45. package/dist/express/index.d.mts +3 -3
  46. package/dist/express/index.d.mts.map +1 -1
  47. package/dist/express/index.mjs +2 -2
  48. package/dist/express/index.mjs.map +1 -1
  49. package/dist/fastify/index.d.mts +9 -4
  50. package/dist/fastify/index.d.mts.map +1 -1
  51. package/dist/fastify/index.mjs +10 -8
  52. package/dist/fastify/index.mjs.map +1 -1
  53. package/dist/{fork-8u_zFOJq.mjs → fork-Bga8x-X4.mjs} +3 -2
  54. package/dist/fork-Bga8x-X4.mjs.map +1 -0
  55. package/dist/hono/index.d.mts +2 -2
  56. package/dist/hono/index.mjs +1 -1
  57. package/dist/{http-6umVAKDW.mjs → http-B6YgAhyN.mjs} +2 -2
  58. package/dist/{http-6umVAKDW.mjs.map → http-B6YgAhyN.mjs.map} +1 -1
  59. package/dist/http.d.mts +1 -1
  60. package/dist/{index-o1_z4phv.d.mts → index-ZSRQP_BI.d.mts} +3 -3
  61. package/dist/{index-o1_z4phv.d.mts.map → index-ZSRQP_BI.d.mts.map} +1 -1
  62. package/dist/index.d.mts +8 -8
  63. package/dist/index.mjs +1 -1
  64. package/dist/index.mjs.map +1 -1
  65. package/dist/{integration-DTZtjSqh.mjs → integration-Dhig7ae6.mjs} +2 -2
  66. package/dist/{integration-DTZtjSqh.mjs.map → integration-Dhig7ae6.mjs.map} +1 -1
  67. package/dist/{logger-DntcxxHg.d.mts → logger-CTcvd5Cc.d.mts} +7 -3
  68. package/dist/logger-CTcvd5Cc.d.mts.map +1 -0
  69. package/dist/logger.d.mts +2 -2
  70. package/dist/logger.mjs +2 -2
  71. package/dist/{middleware-U-lIAzHg.d.mts → middleware-31KhtiEF.d.mts} +2 -2
  72. package/dist/{middleware-U-lIAzHg.d.mts.map → middleware-31KhtiEF.d.mts.map} +1 -1
  73. package/dist/nestjs/index.d.mts +2 -2
  74. package/dist/nestjs/index.mjs +2 -2
  75. package/dist/next/client.d.mts +1 -1
  76. package/dist/next/index.d.mts +6 -5
  77. package/dist/next/index.d.mts.map +1 -1
  78. package/dist/next/index.mjs +3 -3
  79. package/dist/next/index.mjs.map +1 -1
  80. package/dist/next/instrumentation.d.mts +1 -1
  81. package/dist/next/instrumentation.mjs +1 -1
  82. package/dist/next/instrumentation.mjs.map +1 -1
  83. package/dist/nitro/module.d.mts +2 -2
  84. package/dist/nitro/module.d.mts.map +1 -1
  85. package/dist/nitro/module.mjs +7 -2
  86. package/dist/nitro/module.mjs.map +1 -1
  87. package/dist/nitro/plugin.mjs +3 -2
  88. package/dist/nitro/plugin.mjs.map +1 -1
  89. package/dist/nitro/v3/index.d.mts +2 -2
  90. package/dist/nitro/v3/module.d.mts +1 -1
  91. package/dist/nitro/v3/module.d.mts.map +1 -1
  92. package/dist/nitro/v3/module.mjs +9 -4
  93. package/dist/nitro/v3/module.mjs.map +1 -1
  94. package/dist/nitro/v3/plugin.mjs +3 -2
  95. package/dist/nitro/v3/plugin.mjs.map +1 -1
  96. package/dist/nitro/v3/useLogger.d.mts +1 -1
  97. package/dist/{nitro-oZre8ab3.d.mts → nitro-BRddgqSb.d.mts} +2 -2
  98. package/dist/{nitro-oZre8ab3.d.mts.map → nitro-BRddgqSb.d.mts.map} +1 -1
  99. package/dist/nitroConfigBridge-NbFn-sIK.mjs +157 -0
  100. package/dist/nitroConfigBridge-NbFn-sIK.mjs.map +1 -0
  101. package/dist/nuxt/module.d.mts +8 -4
  102. package/dist/nuxt/module.d.mts.map +1 -1
  103. package/dist/nuxt/module.mjs +1 -1
  104. package/dist/nuxt/module.mjs.map +1 -1
  105. package/dist/orpc/index.d.mts +115 -0
  106. package/dist/orpc/index.d.mts.map +1 -0
  107. package/dist/orpc/index.mjs +144 -0
  108. package/dist/orpc/index.mjs.map +1 -0
  109. package/dist/{package-v_MmOZeA.mjs → package-B23bR3tK.mjs} +2 -2
  110. package/dist/package-B23bR3tK.mjs.map +1 -0
  111. package/dist/{parseError-yVZ58wIK.d.mts → parseError-D4PIxEWo.d.mts} +2 -2
  112. package/dist/parseError-D4PIxEWo.d.mts.map +1 -0
  113. package/dist/react-router/index.d.mts +2 -2
  114. package/dist/react-router/index.mjs +2 -2
  115. package/dist/runtime/client/log.d.mts +1 -1
  116. package/dist/runtime/server/routes/_evlog/ingest.post.mjs +28 -12
  117. package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
  118. package/dist/runtime/server/useLogger.d.mts +1 -1
  119. package/dist/runtime/utils/parseError.d.mts +2 -2
  120. package/dist/{storage-Dwinmg8P.mjs → storage-BNubsWwz.mjs} +2 -1
  121. package/dist/{storage-Dwinmg8P.mjs.map → storage-BNubsWwz.mjs.map} +1 -1
  122. package/dist/stream.d.mts +1 -1
  123. package/dist/stream.mjs +1 -1
  124. package/dist/sveltekit/index.d.mts +3 -3
  125. package/dist/sveltekit/index.d.mts.map +1 -1
  126. package/dist/sveltekit/index.mjs +43 -10
  127. package/dist/sveltekit/index.mjs.map +1 -1
  128. package/dist/toolkit.d.mts +6 -6
  129. package/dist/toolkit.mjs +6 -6
  130. package/dist/types.d.mts +1 -1
  131. package/dist/{useLogger-BsPL4AQm.d.mts → useLogger-CqvH6qOf.d.mts} +2 -2
  132. package/dist/{useLogger-BsPL4AQm.d.mts.map → useLogger-CqvH6qOf.d.mts.map} +1 -1
  133. package/dist/{utils-DLCeShxL.d.mts → utils-DxqvIOyR.d.mts} +12 -3
  134. package/dist/{utils-DLCeShxL.d.mts.map → utils-DxqvIOyR.d.mts.map} +1 -1
  135. package/dist/utils.d.mts +1 -1
  136. package/dist/utils.mjs +10 -1
  137. package/dist/utils.mjs.map +1 -1
  138. package/dist/vite/index.d.mts +1 -1
  139. package/dist/workers.d.mts +1 -1
  140. package/dist/workers.mjs +1 -1
  141. package/package.json +48 -15
  142. package/dist/audit-CC8nfazi.d.mts.map +0 -1
  143. package/dist/audit-pV5aLGP0.mjs.map +0 -1
  144. package/dist/drain-X7_5szSI.mjs.map +0 -1
  145. package/dist/fork-8u_zFOJq.mjs.map +0 -1
  146. package/dist/logger-DntcxxHg.d.mts.map +0 -1
  147. package/dist/nitroConfigBridge-DKk7eOn-.mjs +0 -92
  148. package/dist/nitroConfigBridge-DKk7eOn-.mjs.map +0 -1
  149. package/dist/package-v_MmOZeA.mjs.map +0 -1
  150. package/dist/parseError-yVZ58wIK.d.mts.map +0 -1
package/README.md CHANGED
@@ -528,6 +528,38 @@ log.set({ users: { count: 42 } })
528
528
 
529
529
  See the full [nestjs example](https://github.com/HugoRCD/evlog/tree/main/examples/nestjs) for a complete working project.
530
530
 
531
+ ## oRPC
532
+
533
+ ```typescript
534
+ // server/orpc.ts
535
+ import { os } from '@orpc/server'
536
+ import { RPCHandler } from '@orpc/server/fetch'
537
+ import { initLogger } from 'evlog'
538
+ import { evlog, withEvlog, type EvlogOrpcContext } from 'evlog/orpc'
539
+
540
+ initLogger({ env: { service: 'orpc-api' } })
541
+
542
+ const base = os.$context<EvlogOrpcContext>().use(evlog())
543
+
544
+ const router = {
545
+ ping: base.handler(({ context }) => {
546
+ context.log.set({ pinged: true })
547
+ return { ok: true }
548
+ }),
549
+ }
550
+
551
+ const handler = withEvlog(new RPCHandler(router))
552
+
553
+ export default async function fetch(request: Request) {
554
+ const { matched, response } = await handler.handle(request, { prefix: '/rpc' })
555
+ return matched ? response : new Response('Not Found', { status: 404 })
556
+ }
557
+ ```
558
+
559
+ `withEvlog()` wraps the handler and emits one wide event per request; `os.use(evlog())` exposes `context.log` to procedures and tags each event with the procedure path as `operation`. Use `useLogger()` from `evlog/orpc` to access the logger off-context.
560
+
561
+ See the full [orpc example](https://github.com/HugoRCD/evlog/tree/main/examples/orpc) for a complete working project.
562
+
531
563
  ## Browser
532
564
 
533
565
  Use the `log` API on the client side for structured browser logging:
@@ -821,7 +853,7 @@ export default defineNitroPlugin((nitroApp) => {
821
853
  Set environment variables:
822
854
 
823
855
  ```bash
824
- NUXT_AXIOM_TOKEN=xaat-your-token
856
+ NUXT_AXIOM_API_KEY=xaat-your-token
825
857
  NUXT_AXIOM_DATASET=your-dataset
826
858
  ```
827
859
 
@@ -916,9 +948,69 @@ export default defineNitroPlugin((nitroApp) => {
916
948
  Set environment variables:
917
949
 
918
950
  ```bash
919
- NUXT_BETTER_STACK_SOURCE_TOKEN=your-source-token
951
+ NUXT_BETTER_STACK_API_KEY=your-source-token
952
+ ```
953
+
954
+ ### HyperDX
955
+
956
+ ```typescript
957
+ // server/plugins/evlog-drain.ts
958
+ import { createHyperDXDrain } from 'evlog/hyperdx'
959
+
960
+ export default defineNitroPlugin((nitroApp) => {
961
+ nitroApp.hooks.hook('evlog:drain', createHyperDXDrain())
962
+ })
963
+ ```
964
+
965
+ Set environment variables:
966
+
967
+ ```bash
968
+ NUXT_HYPERDX_API_KEY=your-api-key
969
+ # Optional — defaults to https://in-otel.hyperdx.io
970
+ NUXT_HYPERDX_ENDPOINT=https://in-otel.hyperdx.io
971
+ ```
972
+
973
+ ### File System
974
+
975
+ Write wide events to local NDJSON files (`.evlog/logs/` by default):
976
+
977
+ ```typescript
978
+ // server/plugins/evlog-drain.ts
979
+ import { createFsDrain } from 'evlog/fs'
980
+
981
+ export default defineNitroPlugin((nitroApp) => {
982
+ nitroApp.hooks.hook('evlog:drain', createFsDrain())
983
+ })
984
+ ```
985
+
986
+ Set environment variables:
987
+
988
+ ```bash
989
+ NUXT_EVLOG_FS_DIR=.evlog/logs
920
990
  ```
921
991
 
992
+ ### Memory
993
+
994
+ In-memory ring buffer — works in any runtime, including Cloudflare Workers:
995
+
996
+ ```typescript
997
+ // server/plugins/evlog-drain.ts
998
+ import { createMemoryDrain } from 'evlog/memory'
999
+
1000
+ export default defineNitroPlugin((nitroApp) => {
1001
+ nitroApp.hooks.hook('evlog:drain', createMemoryDrain())
1002
+ })
1003
+ ```
1004
+
1005
+ Optional environment variables:
1006
+
1007
+ ```bash
1008
+ NUXT_EVLOG_MEMORY_STORE=default
1009
+ NUXT_EVLOG_MEMORY_MAX_EVENTS=1000
1010
+ ```
1011
+
1012
+ Pair with `readMemoryLogs()` for dev-only agent access over HTTP. See the [Memory adapter docs](https://www.evlog.dev/integrate/adapters/self-hosted/memory).
1013
+
922
1014
  ### Multiple Destinations
923
1015
 
924
1016
  Send logs to multiple services:
@@ -1297,6 +1389,7 @@ try {
1297
1389
  | **Hono** | `app.use(evlog())` with `import { evlog } from 'evlog/hono'` ([example](./examples/hono)) |
1298
1390
  | **Fastify** | `app.register(evlog)` with `import { evlog } from 'evlog/fastify'` ([example](./examples/fastify)) |
1299
1391
  | **Elysia** | `.use(evlog())` with `import { evlog } from 'evlog/elysia'` ([example](./examples/elysia)) |
1392
+ | **oRPC** | `withEvlog(handler)` + `os.use(evlog())` with `import { evlog, withEvlog } from 'evlog/orpc'` ([example](./examples/orpc)) |
1300
1393
  | **Cloudflare Workers** | Manual setup with `import { initWorkersLogger, createWorkersLogger } from 'evlog/workers'` ([example](./examples/workers)) |
1301
1394
  | **Custom** | Build your own with `import { createMiddlewareLogger } from 'evlog/toolkit'` ([guide](https://evlog.dev/extend/custom-framework)) |
1302
1395
  | **Analog** | Nitro v2 module setup |
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  //#region src/adapters/axiom.d.ts
3
3
  interface BaseAxiomConfig {
4
4
  /** Axiom dataset name. */
@@ -1,5 +1,5 @@
1
- import { r as httpPost } from "../http-6umVAKDW.mjs";
2
- import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-X7_5szSI.mjs";
1
+ import { r as httpPost } from "../http-B6YgAhyN.mjs";
2
+ import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-7n3K6kPe.mjs";
3
3
  //#region src/adapters/axiom.ts
4
4
  const AXIOM_FIELDS = [
5
5
  {
@@ -1 +1 @@
1
- {"version":3,"file":"axiom.mjs","names":[],"sources":["../../src/adapters/axiom.ts"],"sourcesContent":["import type { WideEvent } from '../types'\nimport type { ConfigField } from '../shared/config'\nimport { resolveAdapterConfig } from '../shared/config'\nimport { defineHttpDrain } from '../shared/drain'\nimport { httpPost } from '../shared/http'\n\ninterface BaseAxiomConfig {\n /** Axiom dataset name. */\n dataset: string\n /**\n * Axiom API key.\n *\n * @example `xaat-...`\n */\n apiKey: string\n /**\n * @deprecated Renamed to {@link BaseAxiomConfig.apiKey}. Will be removed in\n * the next major version. Pass `apiKey` instead.\n */\n token?: string\n /** Organization ID (required for Personal Access Tokens). */\n orgId?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n /** Number of retry attempts on transient failures. Default: 2 */\n retries?: number\n}\n\ninterface EdgeAxiomConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface EndpointAxiomConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\nexport type AxiomConfig = BaseAxiomConfig & (EdgeAxiomConfig | EndpointAxiomConfig)\n\ntype ResolvedAxiomConfig = BaseAxiomConfig & {\n edgeUrl?: string\n baseUrl?: string\n}\n\nconst AXIOM_FIELDS: ConfigField<ResolvedAxiomConfig>[] = [\n { key: 'dataset', env: ['NUXT_AXIOM_DATASET', 'AXIOM_DATASET'] },\n { key: 'apiKey', env: ['NUXT_AXIOM_API_KEY', 'AXIOM_API_KEY'] },\n // Deprecated env var names — resolved as a fallback for `apiKey` below.\n { key: 'token', env: ['NUXT_AXIOM_TOKEN', 'AXIOM_TOKEN'] },\n { key: 'orgId', env: ['NUXT_AXIOM_ORG_ID', 'AXIOM_ORG_ID'] },\n { key: 'edgeUrl', env: ['NUXT_AXIOM_EDGE_URL', 'AXIOM_EDGE_URL'] },\n { key: 'baseUrl', env: ['NUXT_AXIOM_URL', 'AXIOM_URL'] },\n { key: 'timeout' },\n { key: 'retries' },\n]\n\nlet warnedAboutToken = false\n\nfunction applyApiKeyAlias(config: ResolvedAxiomConfig): ResolvedAxiomConfig {\n if (!config.apiKey && config.token) {\n if (!warnedAboutToken) {\n warnedAboutToken = true\n console.warn('[evlog/axiom] `token` is deprecated, use `apiKey` instead. (Env: NUXT_AXIOM_TOKEN/AXIOM_TOKEN → NUXT_AXIOM_API_KEY/AXIOM_API_KEY.)')\n }\n config.apiKey = config.token\n }\n return config\n}\n\n/**\n * Create a drain function for sending logs to Axiom.\n *\n * Configuration priority (highest to lowest):\n * 1. Overrides passed to createAxiomDrain()\n * 2. runtimeConfig.evlog.axiom\n * 3. runtimeConfig.axiom\n * 4. Environment variables: NUXT_AXIOM_API_KEY, AXIOM_API_KEY (or legacy `*_TOKEN`)\n *\n * @example\n * ```ts\n * // Zero config — set NUXT_AXIOM_API_KEY and NUXT_AXIOM_DATASET\n * initLogger({ drain: createAxiomDrain() })\n *\n * // With overrides\n * initLogger({ drain: createAxiomDrain({ dataset: 'my-dataset' }) })\n * ```\n */\nexport function createAxiomDrain(overrides?: Partial<AxiomConfig>) {\n return defineHttpDrain<AxiomConfig>({\n name: 'axiom',\n resolve: async () => {\n const resolved = await resolveAdapterConfig<ResolvedAxiomConfig>(\n 'axiom',\n AXIOM_FIELDS,\n overrides as Partial<ResolvedAxiomConfig>,\n )\n const config = applyApiKeyAlias(resolved)\n if (!config.dataset || !config.apiKey) {\n console.error('[evlog/axiom] Missing dataset or apiKey. Set NUXT_AXIOM_API_KEY/NUXT_AXIOM_DATASET env vars or pass to createAxiomDrain()')\n return null\n }\n if (config.edgeUrl && config.baseUrl) {\n console.warn('[evlog/axiom] Both edgeUrl and baseUrl are set. edgeUrl takes precedence for ingest.')\n delete config.baseUrl\n }\n return config as AxiomConfig\n },\n encode: (events, config) => {\n const url = resolveIngestUrl(config)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n }\n if (config.orgId) headers['X-Axiom-Org-Id'] = config.orgId\n return { url, headers, body: JSON.stringify(events) }\n },\n })\n}\n\n/**\n * Send a single event to Axiom.\n */\nexport async function sendToAxiom(event: WideEvent, config: AxiomConfig): Promise<void> {\n await sendBatchToAxiom([event], config)\n}\n\n/**\n * Send a batch of events to Axiom.\n */\nexport async function sendBatchToAxiom(events: WideEvent[], config: AxiomConfig): Promise<void> {\n const apiKey = config.apiKey ?? config.token\n if (!apiKey) {\n throw new Error('[evlog/axiom] Missing apiKey')\n }\n const url = resolveIngestUrl(config)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n }\n if (config.orgId) headers['X-Axiom-Org-Id'] = config.orgId\n await httpPost({\n url,\n headers,\n body: JSON.stringify(events),\n timeout: config.timeout ?? 5000,\n retries: config.retries,\n label: 'Axiom',\n source: 'axiom',\n })\n}\n\nfunction resolveIngestUrl(config: AxiomConfig): string {\n const encodedDataset = encodeURIComponent(config.dataset)\n\n if (!config.edgeUrl) {\n const baseUrl = config.baseUrl ?? 'https://api.axiom.co'\n return `${baseUrl}/v1/datasets/${encodedDataset}/ingest`\n }\n\n try {\n const parsed = new URL(config.edgeUrl)\n if (parsed.pathname === '' || parsed.pathname === '/') {\n parsed.pathname = `/v1/ingest/${encodedDataset}`\n return parsed.toString()\n }\n parsed.pathname = parsed.pathname.replace(/\\/+$/, '')\n return parsed.toString()\n } catch {\n console.warn(`[evlog/axiom] edgeUrl \"${config.edgeUrl}\" is not a valid URL, falling back to string concatenation.`)\n const trimmed = config.edgeUrl.replace(/\\/+$/, '')\n return `${trimmed}/v1/ingest/${encodedDataset}`\n }\n}\n"],"mappings":";;;AAqDA,MAAM,eAAmD;CACvD;EAAE,KAAK;EAAW,KAAK,CAAC,sBAAsB,gBAAgB;EAAE;CAChE;EAAE,KAAK;EAAU,KAAK,CAAC,sBAAsB,gBAAgB;EAAE;CAE/D;EAAE,KAAK;EAAS,KAAK,CAAC,oBAAoB,cAAc;EAAE;CAC1D;EAAE,KAAK;EAAS,KAAK,CAAC,qBAAqB,eAAe;EAAE;CAC5D;EAAE,KAAK;EAAW,KAAK,CAAC,uBAAuB,iBAAiB;EAAE;CAClE;EAAE,KAAK;EAAW,KAAK,CAAC,kBAAkB,YAAY;EAAE;CACxD,EAAE,KAAK,WAAW;CAClB,EAAE,KAAK,WAAW;CACnB;AAED,IAAI,mBAAmB;AAEvB,SAAS,iBAAiB,QAAkD;AAC1E,KAAI,CAAC,OAAO,UAAU,OAAO,OAAO;AAClC,MAAI,CAAC,kBAAkB;AACrB,sBAAmB;AACnB,WAAQ,KAAK,qIAAqI;;AAEpJ,SAAO,SAAS,OAAO;;AAEzB,QAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,iBAAiB,WAAkC;AACjE,QAAO,gBAA6B;EAClC,MAAM;EACN,SAAS,YAAY;GAMnB,MAAM,SAAS,iBAAiB,MALT,qBACrB,SACA,cACA,UACD,CACwC;AACzC,OAAI,CAAC,OAAO,WAAW,CAAC,OAAO,QAAQ;AACrC,YAAQ,MAAM,4HAA4H;AAC1I,WAAO;;AAET,OAAI,OAAO,WAAW,OAAO,SAAS;AACpC,YAAQ,KAAK,uFAAuF;AACpG,WAAO,OAAO;;AAEhB,UAAO;;EAET,SAAS,QAAQ,WAAW;GAC1B,MAAM,MAAM,iBAAiB,OAAO;GACpC,MAAM,UAAkC;IACtC,gBAAgB;IAChB,iBAAiB,UAAU,OAAO;IACnC;AACD,OAAI,OAAO,MAAO,SAAQ,oBAAoB,OAAO;AACrD,UAAO;IAAE;IAAK;IAAS,MAAM,KAAK,UAAU,OAAO;IAAE;;EAExD,CAAC;;;;;AAMJ,eAAsB,YAAY,OAAkB,QAAoC;AACtF,OAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO;;;;;AAMzC,eAAsB,iBAAiB,QAAqB,QAAoC;CAC9F,MAAM,SAAS,OAAO,UAAU,OAAO;AACvC,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,+BAA+B;CAEjD,MAAM,MAAM,iBAAiB,OAAO;CACpC,MAAM,UAAkC;EACtC,gBAAgB;EAChB,iBAAiB,UAAU;EAC5B;AACD,KAAI,OAAO,MAAO,SAAQ,oBAAoB,OAAO;AACrD,OAAM,SAAS;EACb;EACA;EACA,MAAM,KAAK,UAAU,OAAO;EAC5B,SAAS,OAAO,WAAW;EAC3B,SAAS,OAAO;EAChB,OAAO;EACP,QAAQ;EACT,CAAC;;AAGJ,SAAS,iBAAiB,QAA6B;CACrD,MAAM,iBAAiB,mBAAmB,OAAO,QAAQ;AAEzD,KAAI,CAAC,OAAO,QAEV,QAAO,GADS,OAAO,WAAW,uBAChB,eAAe,eAAe;AAGlD,KAAI;EACF,MAAM,SAAS,IAAI,IAAI,OAAO,QAAQ;AACtC,MAAI,OAAO,aAAa,MAAM,OAAO,aAAa,KAAK;AACrD,UAAO,WAAW,cAAc;AAChC,UAAO,OAAO,UAAU;;AAE1B,SAAO,WAAW,OAAO,SAAS,QAAQ,QAAQ,GAAG;AACrD,SAAO,OAAO,UAAU;SAClB;AACN,UAAQ,KAAK,0BAA0B,OAAO,QAAQ,6DAA6D;AAEnH,SAAO,GADS,OAAO,QAAQ,QAAQ,QAAQ,GAC9B,CAAC,aAAa"}
1
+ {"version":3,"file":"axiom.mjs","names":[],"sources":["../../src/adapters/axiom.ts"],"sourcesContent":["import type { WideEvent } from '../types'\nimport type { ConfigField } from '../shared/config'\nimport { resolveAdapterConfig } from '../shared/config'\nimport { defineHttpDrain } from '../shared/drain'\nimport { httpPost } from '../shared/http'\n\ninterface BaseAxiomConfig {\n /** Axiom dataset name. */\n dataset: string\n /**\n * Axiom API key.\n *\n * @example `xaat-...`\n */\n apiKey: string\n /**\n * @deprecated Renamed to {@link BaseAxiomConfig.apiKey}. Will be removed in\n * the next major version. Pass `apiKey` instead.\n */\n token?: string\n /** Organization ID (required for Personal Access Tokens). */\n orgId?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n /** Number of retry attempts on transient failures. Default: 2 */\n retries?: number\n}\n\ninterface EdgeAxiomConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface EndpointAxiomConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\nexport type AxiomConfig = BaseAxiomConfig & (EdgeAxiomConfig | EndpointAxiomConfig)\n\ntype ResolvedAxiomConfig = BaseAxiomConfig & {\n edgeUrl?: string\n baseUrl?: string\n}\n\nconst AXIOM_FIELDS: ConfigField<ResolvedAxiomConfig>[] = [\n { key: 'dataset', env: ['NUXT_AXIOM_DATASET', 'AXIOM_DATASET'] },\n { key: 'apiKey', env: ['NUXT_AXIOM_API_KEY', 'AXIOM_API_KEY'] },\n // Deprecated env var names — resolved as a fallback for `apiKey` below.\n { key: 'token', env: ['NUXT_AXIOM_TOKEN', 'AXIOM_TOKEN'] },\n { key: 'orgId', env: ['NUXT_AXIOM_ORG_ID', 'AXIOM_ORG_ID'] },\n { key: 'edgeUrl', env: ['NUXT_AXIOM_EDGE_URL', 'AXIOM_EDGE_URL'] },\n { key: 'baseUrl', env: ['NUXT_AXIOM_URL', 'AXIOM_URL'] },\n { key: 'timeout' },\n { key: 'retries' },\n]\n\nlet warnedAboutToken = false\n\nfunction applyApiKeyAlias(config: Partial<ResolvedAxiomConfig>): Partial<ResolvedAxiomConfig> {\n if (!config.apiKey && config.token) {\n if (!warnedAboutToken) {\n warnedAboutToken = true\n console.warn('[evlog/axiom] `token` is deprecated, use `apiKey` instead. (Env: NUXT_AXIOM_TOKEN/AXIOM_TOKEN → NUXT_AXIOM_API_KEY/AXIOM_API_KEY.)')\n }\n config.apiKey = config.token\n }\n return config\n}\n\n/**\n * Create a drain function for sending logs to Axiom.\n *\n * Configuration priority (highest to lowest):\n * 1. Overrides passed to createAxiomDrain()\n * 2. runtimeConfig.evlog.axiom\n * 3. runtimeConfig.axiom\n * 4. Environment variables: NUXT_AXIOM_API_KEY, AXIOM_API_KEY (or legacy `*_TOKEN`)\n *\n * @example\n * ```ts\n * // Zero config — set NUXT_AXIOM_API_KEY and NUXT_AXIOM_DATASET\n * initLogger({ drain: createAxiomDrain() })\n *\n * // With overrides\n * initLogger({ drain: createAxiomDrain({ dataset: 'my-dataset' }) })\n * ```\n */\nexport function createAxiomDrain(overrides?: Partial<AxiomConfig>) {\n return defineHttpDrain<AxiomConfig>({\n name: 'axiom',\n resolve: async () => {\n const resolved = await resolveAdapterConfig<ResolvedAxiomConfig>(\n 'axiom',\n AXIOM_FIELDS,\n overrides as Partial<ResolvedAxiomConfig>,\n )\n const config = applyApiKeyAlias(resolved)\n if (!config.dataset || !config.apiKey) {\n console.error('[evlog/axiom] Missing dataset or apiKey. Set NUXT_AXIOM_API_KEY/NUXT_AXIOM_DATASET env vars or pass to createAxiomDrain()')\n return null\n }\n if (config.edgeUrl && config.baseUrl) {\n console.warn('[evlog/axiom] Both edgeUrl and baseUrl are set. edgeUrl takes precedence for ingest.')\n delete config.baseUrl\n }\n return config as AxiomConfig\n },\n encode: (events, config) => {\n const url = resolveIngestUrl(config)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n }\n if (config.orgId) headers['X-Axiom-Org-Id'] = config.orgId\n return { url, headers, body: JSON.stringify(events) }\n },\n })\n}\n\n/**\n * Send a single event to Axiom.\n */\nexport async function sendToAxiom(event: WideEvent, config: AxiomConfig): Promise<void> {\n await sendBatchToAxiom([event], config)\n}\n\n/**\n * Send a batch of events to Axiom.\n */\nexport async function sendBatchToAxiom(events: WideEvent[], config: AxiomConfig): Promise<void> {\n const apiKey = config.apiKey ?? config.token\n if (!apiKey) {\n throw new Error('[evlog/axiom] Missing apiKey')\n }\n const url = resolveIngestUrl(config)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n }\n if (config.orgId) headers['X-Axiom-Org-Id'] = config.orgId\n await httpPost({\n url,\n headers,\n body: JSON.stringify(events),\n timeout: config.timeout ?? 5000,\n retries: config.retries,\n label: 'Axiom',\n source: 'axiom',\n })\n}\n\nfunction resolveIngestUrl(config: AxiomConfig): string {\n const encodedDataset = encodeURIComponent(config.dataset)\n\n if (!config.edgeUrl) {\n const baseUrl = config.baseUrl ?? 'https://api.axiom.co'\n return `${baseUrl}/v1/datasets/${encodedDataset}/ingest`\n }\n\n try {\n const parsed = new URL(config.edgeUrl)\n if (parsed.pathname === '' || parsed.pathname === '/') {\n parsed.pathname = `/v1/ingest/${encodedDataset}`\n return parsed.toString()\n }\n parsed.pathname = parsed.pathname.replace(/\\/+$/, '')\n return parsed.toString()\n } catch {\n console.warn(`[evlog/axiom] edgeUrl \"${config.edgeUrl}\" is not a valid URL, falling back to string concatenation.`)\n const trimmed = config.edgeUrl.replace(/\\/+$/, '')\n return `${trimmed}/v1/ingest/${encodedDataset}`\n }\n}\n"],"mappings":";;;AAqDA,MAAM,eAAmD;CACvD;EAAE,KAAK;EAAW,KAAK,CAAC,sBAAsB,gBAAgB;EAAE;CAChE;EAAE,KAAK;EAAU,KAAK,CAAC,sBAAsB,gBAAgB;EAAE;CAE/D;EAAE,KAAK;EAAS,KAAK,CAAC,oBAAoB,cAAc;EAAE;CAC1D;EAAE,KAAK;EAAS,KAAK,CAAC,qBAAqB,eAAe;EAAE;CAC5D;EAAE,KAAK;EAAW,KAAK,CAAC,uBAAuB,iBAAiB;EAAE;CAClE;EAAE,KAAK;EAAW,KAAK,CAAC,kBAAkB,YAAY;EAAE;CACxD,EAAE,KAAK,WAAW;CAClB,EAAE,KAAK,WAAW;CACnB;AAED,IAAI,mBAAmB;AAEvB,SAAS,iBAAiB,QAAoE;AAC5F,KAAI,CAAC,OAAO,UAAU,OAAO,OAAO;AAClC,MAAI,CAAC,kBAAkB;AACrB,sBAAmB;AACnB,WAAQ,KAAK,qIAAqI;;AAEpJ,SAAO,SAAS,OAAO;;AAEzB,QAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,iBAAiB,WAAkC;AACjE,QAAO,gBAA6B;EAClC,MAAM;EACN,SAAS,YAAY;GAMnB,MAAM,SAAS,iBAAiB,MALT,qBACrB,SACA,cACA,UACD,CACwC;AACzC,OAAI,CAAC,OAAO,WAAW,CAAC,OAAO,QAAQ;AACrC,YAAQ,MAAM,4HAA4H;AAC1I,WAAO;;AAET,OAAI,OAAO,WAAW,OAAO,SAAS;AACpC,YAAQ,KAAK,uFAAuF;AACpG,WAAO,OAAO;;AAEhB,UAAO;;EAET,SAAS,QAAQ,WAAW;GAC1B,MAAM,MAAM,iBAAiB,OAAO;GACpC,MAAM,UAAkC;IACtC,gBAAgB;IAChB,iBAAiB,UAAU,OAAO;IACnC;AACD,OAAI,OAAO,MAAO,SAAQ,oBAAoB,OAAO;AACrD,UAAO;IAAE;IAAK;IAAS,MAAM,KAAK,UAAU,OAAO;IAAE;;EAExD,CAAC;;;;;AAMJ,eAAsB,YAAY,OAAkB,QAAoC;AACtF,OAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO;;;;;AAMzC,eAAsB,iBAAiB,QAAqB,QAAoC;CAC9F,MAAM,SAAS,OAAO,UAAU,OAAO;AACvC,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,+BAA+B;CAEjD,MAAM,MAAM,iBAAiB,OAAO;CACpC,MAAM,UAAkC;EACtC,gBAAgB;EAChB,iBAAiB,UAAU;EAC5B;AACD,KAAI,OAAO,MAAO,SAAQ,oBAAoB,OAAO;AACrD,OAAM,SAAS;EACb;EACA;EACA,MAAM,KAAK,UAAU,OAAO;EAC5B,SAAS,OAAO,WAAW;EAC3B,SAAS,OAAO;EAChB,OAAO;EACP,QAAQ;EACT,CAAC;;AAGJ,SAAS,iBAAiB,QAA6B;CACrD,MAAM,iBAAiB,mBAAmB,OAAO,QAAQ;AAEzD,KAAI,CAAC,OAAO,QAEV,QAAO,GADS,OAAO,WAAW,uBAChB,eAAe,eAAe;AAGlD,KAAI;EACF,MAAM,SAAS,IAAI,IAAI,OAAO,QAAQ;AACtC,MAAI,OAAO,aAAa,MAAM,OAAO,aAAa,KAAK;AACrD,UAAO,WAAW,cAAc;AAChC,UAAO,OAAO,UAAU;;AAE1B,SAAO,WAAW,OAAO,SAAS,QAAQ,QAAQ,GAAG;AACrD,SAAO,OAAO,UAAU;SAClB;AACN,UAAQ,KAAK,0BAA0B,OAAO,QAAQ,6DAA6D;AAEnH,SAAO,GADS,OAAO,QAAQ,QAAQ,QAAQ,GAC9B,CAAC,aAAa"}
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  //#region src/adapters/better-stack.d.ts
3
3
  interface BetterStackConfig {
4
4
  /** Better Stack API key (replaces deprecated `sourceToken`). */
@@ -1,5 +1,5 @@
1
- import { r as httpPost } from "../http-6umVAKDW.mjs";
2
- import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-X7_5szSI.mjs";
1
+ import { r as httpPost } from "../http-B6YgAhyN.mjs";
2
+ import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-7n3K6kPe.mjs";
3
3
  //#region src/adapters/better-stack.ts
4
4
  const BETTER_STACK_FIELDS = [
5
5
  {
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  //#region src/adapters/datadog.d.ts
3
3
  interface DatadogConfig {
4
4
  /** Datadog API key with Logs intake permission */
@@ -1,5 +1,5 @@
1
- import { r as httpPost } from "../http-6umVAKDW.mjs";
2
- import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-X7_5szSI.mjs";
1
+ import { r as httpPost } from "../http-B6YgAhyN.mjs";
2
+ import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-7n3K6kPe.mjs";
3
3
  //#region src/adapters/datadog.ts
4
4
  const DATADOG_FIELDS = [
5
5
  {
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, K as LogLevel, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, K as LogLevel, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  //#region src/adapters/fs.d.ts
3
3
  interface FsConfig {
4
4
  /** Directory for log files. Default: `.evlog/logs` */
@@ -1,4 +1,4 @@
1
- import { i as resolveAdapterConfig, t as defineDrain } from "../drain-X7_5szSI.mjs";
1
+ import { i as resolveAdapterConfig, t as defineDrain } from "../drain-7n3K6kPe.mjs";
2
2
  import { join, sep } from "node:path";
3
3
  import { appendFile, mkdir, open, readdir, stat, unlink, writeFile } from "node:fs/promises";
4
4
  import { createReadStream } from "node:fs";
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  import { OTLPConfig } from "./otlp.mjs";
3
3
 
4
4
  //#region src/adapters/hyperdx.d.ts
@@ -1,4 +1,4 @@
1
- import { i as resolveAdapterConfig, t as defineDrain } from "../drain-X7_5szSI.mjs";
1
+ import { i as resolveAdapterConfig, t as defineDrain } from "../drain-7n3K6kPe.mjs";
2
2
  import { sendBatchToOTLP } from "./otlp.mjs";
3
3
  //#region src/adapters/hyperdx.ts
4
4
  /**
@@ -0,0 +1,116 @@
1
+ import { I as DrainContext, K as LogLevel, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
+ //#region src/adapters/memory.d.ts
3
+ /**
4
+ * Configuration for the in-memory drain.
5
+ */
6
+ interface MemoryConfig {
7
+ /** Named store key. Multiple drains sharing the same key share the same buffer. Default: `'default'` */
8
+ store: string;
9
+ /** Maximum number of events to keep in the ring buffer. Oldest events are discarded when the limit is exceeded. Default: `1000` */
10
+ maxEvents: number;
11
+ }
12
+ /**
13
+ * Write events directly into the named store. Exported for direct use and
14
+ * easier testing without going through the drain pipeline.
15
+ */
16
+ declare function writeToMemory(events: WideEvent[], config: MemoryConfig): void;
17
+ /**
18
+ * Create a drain that stores wide events in an in-memory ring buffer.
19
+ *
20
+ * Works in **any** runtime — including Cloudflare Workers (workerd) — where
21
+ * the filesystem (`evlog/fs`) is not available. Pair it with a dev-only HTTP
22
+ * endpoint to let agents retrieve the buffer over HTTP.
23
+ *
24
+ * Configuration priority (highest to lowest):
25
+ * 1. Overrides passed to `createMemoryDrain()`
26
+ * 2. `runtimeConfig.evlog.memory` / `runtimeConfig.memory` (Nitro)
27
+ * 3. Environment variables: `NUXT_EVLOG_MEMORY_STORE`, `EVLOG_MEMORY_STORE`,
28
+ * `NUXT_EVLOG_MEMORY_MAX_EVENTS`, `EVLOG_MEMORY_MAX_EVENTS`
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * // Hono + Cloudflare Workers
33
+ * import { createMemoryDrain, readMemoryLogs } from 'evlog/memory'
34
+ *
35
+ * app.use(evlog({ drain: createMemoryDrain() }))
36
+ *
37
+ * // Dev-only endpoint for agent retrieval
38
+ * if (env.NODE_ENV === 'development') {
39
+ * app.get('/_evlog/logs', (c) => c.json(readMemoryLogs()))
40
+ * }
41
+ * ```
42
+ */
43
+ declare function createMemoryDrain(overrides?: Partial<MemoryConfig>): (ctx: DrainContext | DrainContext[]) => Promise<void>;
44
+ /** Options accepted by {@link readMemoryLogs}. */
45
+ interface ReadMemoryLogsOptions {
46
+ /** Named store to read from. Default: `'default'` */
47
+ store?: string;
48
+ /** Only include events with `timestamp >= since`. */
49
+ since?: Date | string;
50
+ /** Only include events with `timestamp <= until`. */
51
+ until?: Date | string;
52
+ /** Filter by log level. */
53
+ level?: LogLevel | LogLevel[];
54
+ /** Custom predicate — return `false` to skip the event. */
55
+ filter?: (event: WideEvent) => boolean;
56
+ /** Return at most this many of the most-recent matching events. */
57
+ limit?: number;
58
+ }
59
+ /**
60
+ * Read events from the named in-memory store. Returns a snapshot of the
61
+ * buffer with optional filtering, ordered oldest-first.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { readMemoryLogs } from 'evlog/memory'
66
+ *
67
+ * // All events
68
+ * const events = readMemoryLogs()
69
+ *
70
+ * // Errors in the last hour
71
+ * const errors = readMemoryLogs({
72
+ * level: 'error',
73
+ * since: new Date(Date.now() - 60 * 60 * 1000),
74
+ * })
75
+ *
76
+ * // Expose as a JSON endpoint
77
+ * app.get('/_evlog/logs', (c) => c.json(readMemoryLogs({ limit: 200 })))
78
+ * ```
79
+ */
80
+ declare function readMemoryLogs(options?: ReadMemoryLogsOptions): WideEvent[];
81
+ /**
82
+ * Clear all events from a named store (or `'default'`).
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * clearMemoryLogs() // clears the default store
87
+ * clearMemoryLogs('my-store') // clears a named store
88
+ * ```
89
+ */
90
+ declare function clearMemoryLogs(store?: string): void;
91
+ /**
92
+ * Parse a flat query-string object (e.g. from `c.req.query()` in Hono, or
93
+ * `req.query` in Express) into {@link ReadMemoryLogsOptions} with proper type
94
+ * coercion.
95
+ *
96
+ * This lets agents discover and pass filter parameters through HTTP query
97
+ * strings directly:
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * // Hono — zero glue
102
+ * app.get('/_evlog/logs', (c) =>
103
+ * c.json(readMemoryLogs(parseReadMemoryLogsQuery(c.req.query()))))
104
+ *
105
+ * // Express
106
+ * app.get('/_evlog/logs', (req, res) =>
107
+ * res.json(readMemoryLogs(parseReadMemoryLogsQuery(req.query as Record<string, string>))))
108
+ * ```
109
+ *
110
+ * Supported query params: `store`, `since`, `until`, `level` (comma-separated),
111
+ * `limit`. The `filter` predicate cannot be expressed as a query param.
112
+ */
113
+ declare function parseReadMemoryLogsQuery(query: Record<string, string | string[] | undefined>): ReadMemoryLogsOptions;
114
+ //#endregion
115
+ export { MemoryConfig, ReadMemoryLogsOptions, clearMemoryLogs, createMemoryDrain, parseReadMemoryLogsQuery, readMemoryLogs, writeToMemory };
116
+ //# sourceMappingURL=memory.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.mts","names":[],"sources":["../../src/adapters/memory.ts"],"mappings":";;;;;UAQiB,YAAA;EAAY;EAE3B,KAAA;EAAA;EAEA,SAAA;AAAA;;;;;iBA2Cc,aAAA,CAAc,MAAA,EAAQ,SAAA,IAAa,MAAA,EAAQ,YAAA;;;;;AAmC3D;;;;;;;;;;;;;;;;;;;AAYA;;;iBAZgB,iBAAA,CAAkB,SAAA,GAAY,OAAA,CAAQ,YAAA,KAAa,GAAA,EAAd,YAAA,GAAc,YAAA,OAAA,OAAA;;UAYlD,qBAAA;EAQI;EANnB,KAAA;EAQ0B;EAN1B,KAAA,GAAQ,IAAA;EAFR;EAIA,KAAA,GAAQ,IAAA;EAFA;EAIR,KAAA,GAAQ,QAAA,GAAW,QAAA;EAFX;EAIR,MAAA,IAAU,KAAA,EAAO,SAAA;EAFT;EAIR,KAAA;AAAA;;;;;;AA+BF;;;;;;;;;AAuCA;;;;;AA6BA;;iBApEgB,cAAA,CAAe,OAAA,GAAS,qBAAA,GAA6B,SAAA;;;;;;;;;;iBAuCrD,eAAA,CAAgB,KAAA;;;;;;;;;;;;;;;;;;;;;;;iBA6BhB,wBAAA,CACd,KAAA,EAAO,MAAA,0CACN,qBAAA"}
@@ -0,0 +1,191 @@
1
+ import { i as resolveAdapterConfig, t as defineDrain } from "../drain-7n3K6kPe.mjs";
2
+ //#region src/adapters/memory.ts
3
+ const DEFAULT_STORE = "default";
4
+ const DEFAULT_MAX_EVENTS = 1e3;
5
+ const MEMORY_FIELDS = [{
6
+ key: "store",
7
+ env: ["NUXT_EVLOG_MEMORY_STORE", "EVLOG_MEMORY_STORE"]
8
+ }, {
9
+ key: "maxEvents",
10
+ env: ["NUXT_EVLOG_MEMORY_MAX_EVENTS", "EVLOG_MEMORY_MAX_EVENTS"]
11
+ }];
12
+ const stores = /* @__PURE__ */ new Map();
13
+ function getOrCreateStore(name) {
14
+ if (!stores.has(name)) stores.set(name, []);
15
+ return stores.get(name);
16
+ }
17
+ function parseMaxEvents(value) {
18
+ if (typeof value === "number" && Number.isFinite(value)) {
19
+ const n = Math.floor(value);
20
+ return n > 0 ? n : void 0;
21
+ }
22
+ if (typeof value === "string" && value) {
23
+ const parsed = Number.parseFloat(value);
24
+ if (!Number.isFinite(parsed)) return void 0;
25
+ const n = Math.floor(parsed);
26
+ return n > 0 ? n : void 0;
27
+ }
28
+ }
29
+ function resolveMemoryConfig(overrides) {
30
+ return {
31
+ store: overrides?.store ?? DEFAULT_STORE,
32
+ maxEvents: parseMaxEvents(overrides?.maxEvents) ?? DEFAULT_MAX_EVENTS
33
+ };
34
+ }
35
+ /**
36
+ * Write events directly into the named store. Exported for direct use and
37
+ * easier testing without going through the drain pipeline.
38
+ */
39
+ function writeToMemory(events, config) {
40
+ if (events.length === 0) return;
41
+ const store = getOrCreateStore(config.store);
42
+ store.push(...events);
43
+ if (store.length > config.maxEvents) store.splice(0, store.length - config.maxEvents);
44
+ }
45
+ /**
46
+ * Create a drain that stores wide events in an in-memory ring buffer.
47
+ *
48
+ * Works in **any** runtime — including Cloudflare Workers (workerd) — where
49
+ * the filesystem (`evlog/fs`) is not available. Pair it with a dev-only HTTP
50
+ * endpoint to let agents retrieve the buffer over HTTP.
51
+ *
52
+ * Configuration priority (highest to lowest):
53
+ * 1. Overrides passed to `createMemoryDrain()`
54
+ * 2. `runtimeConfig.evlog.memory` / `runtimeConfig.memory` (Nitro)
55
+ * 3. Environment variables: `NUXT_EVLOG_MEMORY_STORE`, `EVLOG_MEMORY_STORE`,
56
+ * `NUXT_EVLOG_MEMORY_MAX_EVENTS`, `EVLOG_MEMORY_MAX_EVENTS`
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * // Hono + Cloudflare Workers
61
+ * import { createMemoryDrain, readMemoryLogs } from 'evlog/memory'
62
+ *
63
+ * app.use(evlog({ drain: createMemoryDrain() }))
64
+ *
65
+ * // Dev-only endpoint for agent retrieval
66
+ * if (env.NODE_ENV === 'development') {
67
+ * app.get('/_evlog/logs', (c) => c.json(readMemoryLogs()))
68
+ * }
69
+ * ```
70
+ */
71
+ function createMemoryDrain(overrides) {
72
+ return defineDrain({
73
+ name: "memory",
74
+ resolve: async () => {
75
+ return resolveMemoryConfig(await resolveAdapterConfig("memory", MEMORY_FIELDS, overrides));
76
+ },
77
+ send: (events, cfg) => Promise.resolve(writeToMemory(events, cfg))
78
+ });
79
+ }
80
+ function normalizeTimestamp(value) {
81
+ if (!value) return void 0;
82
+ const ts = (value instanceof Date ? value : new Date(value)).getTime();
83
+ return Number.isNaN(ts) ? void 0 : ts;
84
+ }
85
+ /**
86
+ * Read events from the named in-memory store. Returns a snapshot of the
87
+ * buffer with optional filtering, ordered oldest-first.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * import { readMemoryLogs } from 'evlog/memory'
92
+ *
93
+ * // All events
94
+ * const events = readMemoryLogs()
95
+ *
96
+ * // Errors in the last hour
97
+ * const errors = readMemoryLogs({
98
+ * level: 'error',
99
+ * since: new Date(Date.now() - 60 * 60 * 1000),
100
+ * })
101
+ *
102
+ * // Expose as a JSON endpoint
103
+ * app.get('/_evlog/logs', (c) => c.json(readMemoryLogs({ limit: 200 })))
104
+ * ```
105
+ */
106
+ function readMemoryLogs(options = {}) {
107
+ const storeName = options.store ?? DEFAULT_STORE;
108
+ const events = [...stores.get(storeName) ?? []];
109
+ const sinceMs = normalizeTimestamp(options.since);
110
+ const untilMs = normalizeTimestamp(options.until);
111
+ const levels = options.level ? new Set(Array.isArray(options.level) ? options.level : [options.level]) : void 0;
112
+ const custom = options.filter;
113
+ const filtered = events.filter((event) => {
114
+ if (levels && !levels.has(event.level)) return false;
115
+ if (sinceMs !== void 0 || untilMs !== void 0) {
116
+ const ts = typeof event.timestamp === "string" ? Date.parse(event.timestamp) : NaN;
117
+ if (Number.isNaN(ts)) return false;
118
+ if (sinceMs !== void 0 && ts < sinceMs) return false;
119
+ if (untilMs !== void 0 && ts > untilMs) return false;
120
+ }
121
+ if (custom && !custom(event)) return false;
122
+ return true;
123
+ });
124
+ if (options.limit !== void 0) {
125
+ if (options.limit <= 0) return [];
126
+ if (filtered.length > options.limit) return filtered.slice(-options.limit);
127
+ }
128
+ return filtered;
129
+ }
130
+ /**
131
+ * Clear all events from a named store (or `'default'`).
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * clearMemoryLogs() // clears the default store
136
+ * clearMemoryLogs('my-store') // clears a named store
137
+ * ```
138
+ */
139
+ function clearMemoryLogs(store = DEFAULT_STORE) {
140
+ const s = stores.get(store);
141
+ if (s) s.length = 0;
142
+ }
143
+ const VALID_LEVELS = new Set([
144
+ "info",
145
+ "error",
146
+ "warn",
147
+ "debug"
148
+ ]);
149
+ /**
150
+ * Parse a flat query-string object (e.g. from `c.req.query()` in Hono, or
151
+ * `req.query` in Express) into {@link ReadMemoryLogsOptions} with proper type
152
+ * coercion.
153
+ *
154
+ * This lets agents discover and pass filter parameters through HTTP query
155
+ * strings directly:
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * // Hono — zero glue
160
+ * app.get('/_evlog/logs', (c) =>
161
+ * c.json(readMemoryLogs(parseReadMemoryLogsQuery(c.req.query()))))
162
+ *
163
+ * // Express
164
+ * app.get('/_evlog/logs', (req, res) =>
165
+ * res.json(readMemoryLogs(parseReadMemoryLogsQuery(req.query as Record<string, string>))))
166
+ * ```
167
+ *
168
+ * Supported query params: `store`, `since`, `until`, `level` (comma-separated),
169
+ * `limit`. The `filter` predicate cannot be expressed as a query param.
170
+ */
171
+ function parseReadMemoryLogsQuery(query) {
172
+ const opts = {};
173
+ const { store, since, until, level, limit } = query;
174
+ if (typeof store === "string" && store) opts.store = store;
175
+ if (typeof since === "string" && since) opts.since = since;
176
+ if (typeof until === "string" && until) opts.until = until;
177
+ if (level !== void 0) {
178
+ const levels = (Array.isArray(level) ? level : level.split(",")).map((l) => l.trim()).filter((l) => VALID_LEVELS.has(l));
179
+ if (levels.length === 1) [opts.level] = levels;
180
+ else if (levels.length > 1) opts.level = levels;
181
+ }
182
+ if (typeof limit === "string") {
183
+ const n = Number.parseInt(limit, 10);
184
+ if (!Number.isNaN(n)) opts.limit = n;
185
+ }
186
+ return opts;
187
+ }
188
+ //#endregion
189
+ export { clearMemoryLogs, createMemoryDrain, parseReadMemoryLogsQuery, readMemoryLogs, writeToMemory };
190
+
191
+ //# sourceMappingURL=memory.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.mjs","names":[],"sources":["../../src/adapters/memory.ts"],"sourcesContent":["import type { LogLevel, WideEvent } from '../types'\nimport type { ConfigField } from '../shared/config'\nimport { resolveAdapterConfig } from '../shared/config'\nimport { defineDrain } from '../shared/drain'\n\n/**\n * Configuration for the in-memory drain.\n */\nexport interface MemoryConfig {\n /** Named store key. Multiple drains sharing the same key share the same buffer. Default: `'default'` */\n store: string\n /** Maximum number of events to keep in the ring buffer. Oldest events are discarded when the limit is exceeded. Default: `1000` */\n maxEvents: number\n}\n\nconst DEFAULT_STORE = 'default'\nconst DEFAULT_MAX_EVENTS = 1000\n\nconst MEMORY_FIELDS: ConfigField<Partial<MemoryConfig>>[] = [\n { key: 'store', env: ['NUXT_EVLOG_MEMORY_STORE', 'EVLOG_MEMORY_STORE'] },\n { key: 'maxEvents', env: ['NUXT_EVLOG_MEMORY_MAX_EVENTS', 'EVLOG_MEMORY_MAX_EVENTS'] },\n]\n\nconst stores = new Map<string, WideEvent[]>()\n\nfunction getOrCreateStore(name: string): WideEvent[] {\n if (!stores.has(name)) stores.set(name, [])\n return stores.get(name)!\n}\n\nfunction parseMaxEvents(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) {\n const n = Math.floor(value)\n return n > 0 ? n : undefined\n }\n if (typeof value === 'string' && value) {\n const parsed = Number.parseFloat(value)\n if (!Number.isFinite(parsed)) return undefined\n const n = Math.floor(parsed)\n return n > 0 ? n : undefined\n }\n return undefined\n}\n\nfunction resolveMemoryConfig(overrides?: Partial<MemoryConfig>): MemoryConfig {\n return {\n store: overrides?.store ?? DEFAULT_STORE,\n maxEvents: parseMaxEvents(overrides?.maxEvents) ?? DEFAULT_MAX_EVENTS,\n }\n}\n\n/**\n * Write events directly into the named store. Exported for direct use and\n * easier testing without going through the drain pipeline.\n */\nexport function writeToMemory(events: WideEvent[], config: MemoryConfig): void {\n if (events.length === 0) return\n const store = getOrCreateStore(config.store)\n store.push(...events)\n if (store.length > config.maxEvents) {\n store.splice(0, store.length - config.maxEvents)\n }\n}\n\n/**\n * Create a drain that stores wide events in an in-memory ring buffer.\n *\n * Works in **any** runtime — including Cloudflare Workers (workerd) — where\n * the filesystem (`evlog/fs`) is not available. Pair it with a dev-only HTTP\n * endpoint to let agents retrieve the buffer over HTTP.\n *\n * Configuration priority (highest to lowest):\n * 1. Overrides passed to `createMemoryDrain()`\n * 2. `runtimeConfig.evlog.memory` / `runtimeConfig.memory` (Nitro)\n * 3. Environment variables: `NUXT_EVLOG_MEMORY_STORE`, `EVLOG_MEMORY_STORE`,\n * `NUXT_EVLOG_MEMORY_MAX_EVENTS`, `EVLOG_MEMORY_MAX_EVENTS`\n *\n * @example\n * ```ts\n * // Hono + Cloudflare Workers\n * import { createMemoryDrain, readMemoryLogs } from 'evlog/memory'\n *\n * app.use(evlog({ drain: createMemoryDrain() }))\n *\n * // Dev-only endpoint for agent retrieval\n * if (env.NODE_ENV === 'development') {\n * app.get('/_evlog/logs', (c) => c.json(readMemoryLogs()))\n * }\n * ```\n */\nexport function createMemoryDrain(overrides?: Partial<MemoryConfig>) {\n return defineDrain<MemoryConfig>({\n name: 'memory',\n resolve: async () => {\n const resolved = await resolveAdapterConfig<Partial<MemoryConfig>>('memory', MEMORY_FIELDS, overrides)\n return resolveMemoryConfig(resolved)\n },\n send: (events, cfg) => Promise.resolve(writeToMemory(events, cfg)),\n })\n}\n\n/** Options accepted by {@link readMemoryLogs}. */\nexport interface ReadMemoryLogsOptions {\n /** Named store to read from. Default: `'default'` */\n store?: string\n /** Only include events with `timestamp >= since`. */\n since?: Date | string\n /** Only include events with `timestamp <= until`. */\n until?: Date | string\n /** Filter by log level. */\n level?: LogLevel | LogLevel[]\n /** Custom predicate — return `false` to skip the event. */\n filter?: (event: WideEvent) => boolean\n /** Return at most this many of the most-recent matching events. */\n limit?: number\n}\n\nfunction normalizeTimestamp(value: Date | string | undefined): number | undefined {\n if (!value) return undefined\n const date = value instanceof Date ? value : new Date(value)\n const ts = date.getTime()\n return Number.isNaN(ts) ? undefined : ts\n}\n\n/**\n * Read events from the named in-memory store. Returns a snapshot of the\n * buffer with optional filtering, ordered oldest-first.\n *\n * @example\n * ```ts\n * import { readMemoryLogs } from 'evlog/memory'\n *\n * // All events\n * const events = readMemoryLogs()\n *\n * // Errors in the last hour\n * const errors = readMemoryLogs({\n * level: 'error',\n * since: new Date(Date.now() - 60 * 60 * 1000),\n * })\n *\n * // Expose as a JSON endpoint\n * app.get('/_evlog/logs', (c) => c.json(readMemoryLogs({ limit: 200 })))\n * ```\n */\nexport function readMemoryLogs(options: ReadMemoryLogsOptions = {}): WideEvent[] {\n const storeName = options.store ?? DEFAULT_STORE\n const events = [...(stores.get(storeName) ?? [])]\n\n const sinceMs = normalizeTimestamp(options.since)\n const untilMs = normalizeTimestamp(options.until)\n const levels = options.level\n ? new Set<LogLevel>(Array.isArray(options.level) ? options.level : [options.level])\n : undefined\n const custom = options.filter\n\n const filtered = events.filter((event) => {\n if (levels && !levels.has(event.level)) return false\n if (sinceMs !== undefined || untilMs !== undefined) {\n const ts = typeof event.timestamp === 'string' ? Date.parse(event.timestamp) : Number.NaN\n if (Number.isNaN(ts)) return false\n if (sinceMs !== undefined && ts < sinceMs) return false\n if (untilMs !== undefined && ts > untilMs) return false\n }\n if (custom && !custom(event)) return false\n return true\n })\n\n if (options.limit !== undefined) {\n if (options.limit <= 0) return []\n if (filtered.length > options.limit) return filtered.slice(-options.limit)\n }\n return filtered\n}\n\n/**\n * Clear all events from a named store (or `'default'`).\n *\n * @example\n * ```ts\n * clearMemoryLogs() // clears the default store\n * clearMemoryLogs('my-store') // clears a named store\n * ```\n */\nexport function clearMemoryLogs(store = DEFAULT_STORE): void {\n const s = stores.get(store)\n if (s) s.length = 0\n}\n\nconst VALID_LEVELS = new Set<LogLevel>(['info', 'error', 'warn', 'debug'])\n\n/**\n * Parse a flat query-string object (e.g. from `c.req.query()` in Hono, or\n * `req.query` in Express) into {@link ReadMemoryLogsOptions} with proper type\n * coercion.\n *\n * This lets agents discover and pass filter parameters through HTTP query\n * strings directly:\n *\n * @example\n * ```ts\n * // Hono — zero glue\n * app.get('/_evlog/logs', (c) =>\n * c.json(readMemoryLogs(parseReadMemoryLogsQuery(c.req.query()))))\n *\n * // Express\n * app.get('/_evlog/logs', (req, res) =>\n * res.json(readMemoryLogs(parseReadMemoryLogsQuery(req.query as Record<string, string>))))\n * ```\n *\n * Supported query params: `store`, `since`, `until`, `level` (comma-separated),\n * `limit`. The `filter` predicate cannot be expressed as a query param.\n */\nexport function parseReadMemoryLogsQuery(\n query: Record<string, string | string[] | undefined>,\n): ReadMemoryLogsOptions {\n const opts: ReadMemoryLogsOptions = {}\n const { store, since, until, level, limit } = query\n\n if (typeof store === 'string' && store) opts.store = store\n if (typeof since === 'string' && since) opts.since = since\n if (typeof until === 'string' && until) opts.until = until\n\n if (level !== undefined) {\n const raw = Array.isArray(level) ? level : level.split(',')\n const levels = raw.map((l) => l.trim()).filter((l): l is LogLevel => VALID_LEVELS.has(l as LogLevel))\n if (levels.length === 1) [opts.level] = levels\n else if (levels.length > 1) opts.level = levels\n }\n\n if (typeof limit === 'string') {\n const n = Number.parseInt(limit, 10)\n if (!Number.isNaN(n)) opts.limit = n\n }\n\n return opts\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  //#region src/adapters/otlp.d.ts
3
3
  interface OTLPConfig {
4
4
  /** OTLP HTTP endpoint (e.g., http://localhost:4318) */
@@ -1,5 +1,5 @@
1
- import { r as httpPost } from "../http-6umVAKDW.mjs";
2
- import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-X7_5szSI.mjs";
1
+ import { r as httpPost } from "../http-B6YgAhyN.mjs";
2
+ import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-7n3K6kPe.mjs";
3
3
  import { n as toOtlpAttributeValue } from "../event-1BMl7o0k.mjs";
4
4
  import { n as OTEL_SEVERITY_TEXT, t as OTEL_SEVERITY_NUMBER } from "../severity-R5Egq3qz.mjs";
5
5
  //#region src/adapters/otlp.ts
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  //#region src/adapters/posthog.d.ts
3
3
  /**
4
4
  * Mode for {@link createPostHogDrain}.
@@ -1,5 +1,5 @@
1
- import { r as httpPost } from "../http-6umVAKDW.mjs";
2
- import { i as resolveAdapterConfig, n as defineHttpDrain, t as defineDrain } from "../drain-X7_5szSI.mjs";
1
+ import { r as httpPost } from "../http-B6YgAhyN.mjs";
2
+ import { i as resolveAdapterConfig, n as defineHttpDrain, t as defineDrain } from "../drain-7n3K6kPe.mjs";
3
3
  import { sendBatchToOTLP } from "./otlp.mjs";
4
4
  //#region src/adapters/posthog.ts
5
5
  const POSTHOG_FIELDS = [
@@ -1,4 +1,4 @@
1
- import { I as DrainContext, ct as WideEvent } from "../audit-CC8nfazi.mjs";
1
+ import { I as DrainContext, ct as WideEvent } from "../audit-DVdkntSO.mjs";
2
2
  //#region src/adapters/sentry.d.ts
3
3
  interface SentryConfig {
4
4
  /** Sentry DSN */
@@ -1,5 +1,5 @@
1
- import { r as httpPost } from "../http-6umVAKDW.mjs";
2
- import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-X7_5szSI.mjs";
1
+ import { r as httpPost } from "../http-B6YgAhyN.mjs";
2
+ import { i as resolveAdapterConfig, n as defineHttpDrain } from "../drain-7n3K6kPe.mjs";
3
3
  import { t as OTEL_SEVERITY_NUMBER } from "../severity-R5Egq3qz.mjs";
4
4
  //#region src/adapters/sentry.ts
5
5
  const SENTRY_FIELDS = [
@@ -1,4 +1,4 @@
1
- import { $ as RequestLogger } from "../audit-CC8nfazi.mjs";
1
+ import { $ as RequestLogger } from "../audit-DVdkntSO.mjs";
2
2
  import { GatewayModelId, TelemetryIntegration } from "ai";
3
3
  import { LanguageModelV3, LanguageModelV3Middleware } from "@ai-sdk/provider";
4
4