evlog 2.17.0 → 2.19.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.
- package/README.md +95 -2
- package/dist/adapters/axiom.d.mts +1 -1
- package/dist/adapters/axiom.mjs +2 -2
- package/dist/adapters/axiom.mjs.map +1 -1
- package/dist/adapters/better-stack.d.mts +1 -1
- package/dist/adapters/better-stack.mjs +2 -2
- package/dist/adapters/datadog.d.mts +1 -1
- package/dist/adapters/datadog.mjs +2 -2
- package/dist/adapters/fs.d.mts +1 -1
- package/dist/adapters/fs.mjs +2 -2
- package/dist/adapters/hyperdx.d.mts +1 -1
- package/dist/adapters/hyperdx.mjs +1 -1
- package/dist/adapters/memory.d.mts +116 -0
- package/dist/adapters/memory.d.mts.map +1 -0
- package/dist/adapters/memory.mjs +191 -0
- package/dist/adapters/memory.mjs.map +1 -0
- package/dist/adapters/otlp.d.mts +1 -1
- package/dist/adapters/otlp.mjs +4 -4
- package/dist/adapters/posthog.d.mts +1 -1
- package/dist/adapters/posthog.mjs +2 -2
- package/dist/adapters/sentry.d.mts +1 -1
- package/dist/adapters/sentry.mjs +3 -3
- package/dist/ai/index.d.mts +1 -1
- package/dist/{audit-pV5aLGP0.mjs → audit-BFwTUxBJ.mjs} +475 -151
- package/dist/audit-BFwTUxBJ.mjs.map +1 -0
- package/dist/{audit-CC8nfazi.d.mts → audit-BUAajsPU.d.mts} +126 -35
- package/dist/audit-BUAajsPU.d.mts.map +1 -0
- package/dist/better-auth/index.d.mts +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/{define-D6OJdSUH.mjs → define-Bpaymi-h.mjs} +2 -1
- package/dist/define-Bpaymi-h.mjs.map +1 -0
- package/dist/{define-MSdhzmXn.d.mts → define-DGwZkZ7x.d.mts} +8 -3
- package/dist/define-DGwZkZ7x.d.mts.map +1 -0
- package/dist/dev-terminal-D4UaEm17.mjs +54 -0
- package/dist/dev-terminal-D4UaEm17.mjs.map +1 -0
- package/dist/{dist-H3GIh-KK.mjs → dist-DdQWiZn8.mjs} +1 -1
- package/dist/{dist-H3GIh-KK.mjs.map → dist-DdQWiZn8.mjs.map} +1 -1
- package/dist/{drain-X7_5szSI.mjs → drain-D_fy7m0n.mjs} +3 -3
- package/dist/drain-D_fy7m0n.mjs.map +1 -0
- package/dist/elysia/index.d.mts +3 -3
- package/dist/elysia/index.d.mts.map +1 -1
- package/dist/elysia/index.mjs +8 -5
- package/dist/elysia/index.mjs.map +1 -1
- package/dist/enrich-drain-CG_2Nix-.mjs +122 -0
- package/dist/enrich-drain-CG_2Nix-.mjs.map +1 -0
- package/dist/{enricher-DxgML6IC.d.mts → enricher-CuMbbdqp.d.mts} +2 -2
- package/dist/{enricher-DxgML6IC.d.mts.map → enricher-CuMbbdqp.d.mts.map} +1 -1
- package/dist/{enricher-N0erZS87.mjs → enricher-DAWf2-Fx.mjs} +2 -2
- package/dist/{enricher-N0erZS87.mjs.map → enricher-DAWf2-Fx.mjs.map} +1 -1
- package/dist/enrichers.d.mts +2 -2
- package/dist/enrichers.mjs +2 -2
- package/dist/{error-CpbbtyXL.d.mts → error-DwajXSKM.d.mts} +2 -2
- package/dist/{error-CpbbtyXL.d.mts.map → error-DwajXSKM.d.mts.map} +1 -1
- package/dist/error.d.mts +1 -1
- package/dist/{errors-DySW1F9_.d.mts → errors-CAq8pYpW.d.mts} +2 -2
- package/dist/{errors-DySW1F9_.d.mts.map → errors-CAq8pYpW.d.mts.map} +1 -1
- package/dist/{errors-BQgyQ9xe.mjs → errors-DA0cyr8q.mjs} +1 -1
- package/dist/{errors-BQgyQ9xe.mjs.map → errors-DA0cyr8q.mjs.map} +1 -1
- package/dist/{event-1BMl7o0k.mjs → event-qwAv-7AZ.mjs} +1 -1
- package/dist/{event-1BMl7o0k.mjs.map → event-qwAv-7AZ.mjs.map} +1 -1
- package/dist/express/index.d.mts +3 -3
- package/dist/express/index.d.mts.map +1 -1
- package/dist/express/index.mjs +3 -3
- package/dist/express/index.mjs.map +1 -1
- package/dist/fastify/index.d.mts +9 -4
- package/dist/fastify/index.d.mts.map +1 -1
- package/dist/fastify/index.mjs +10 -8
- package/dist/fastify/index.mjs.map +1 -1
- package/dist/{fork-8u_zFOJq.mjs → fork-CYm453dq.mjs} +40 -14
- package/dist/fork-CYm453dq.mjs.map +1 -0
- package/dist/{headers-CU-QqnYg.mjs → headers-VtmnWcfn.mjs} +1 -1
- package/dist/{headers-CU-QqnYg.mjs.map → headers-VtmnWcfn.mjs.map} +1 -1
- package/dist/hono/index.d.mts +2 -2
- package/dist/hono/index.d.mts.map +1 -1
- package/dist/hono/index.mjs +10 -2
- package/dist/hono/index.mjs.map +1 -1
- package/dist/{http-6umVAKDW.mjs → http-Bept5EIC.mjs} +2 -2
- package/dist/{http-6umVAKDW.mjs.map → http-Bept5EIC.mjs.map} +1 -1
- package/dist/http.d.mts +1 -1
- package/dist/{index-o1_z4phv.d.mts → index-CE7kH0II.d.mts} +15 -8
- package/dist/index-CE7kH0II.d.mts.map +1 -0
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +9 -15
- package/dist/index.mjs.map +1 -1
- package/dist/{integration-DTZtjSqh.mjs → integration-CR601uyW.mjs} +3 -3
- package/dist/{integration-DTZtjSqh.mjs.map → integration-CR601uyW.mjs.map} +1 -1
- package/dist/{logger-DntcxxHg.d.mts → logger-BccCJUyD.d.mts} +11 -3
- package/dist/logger-BccCJUyD.d.mts.map +1 -0
- package/dist/logger.d.mts +2 -2
- package/dist/logger.mjs +2 -2
- package/dist/{middleware-U-lIAzHg.d.mts → middleware-DQ6-h8h0.d.mts} +9 -2
- package/dist/middleware-DQ6-h8h0.d.mts.map +1 -0
- package/dist/nestjs/index.d.mts +2 -2
- package/dist/nestjs/index.mjs +4 -4
- package/dist/next/client.d.mts +1 -1
- package/dist/next/index.d.mts +6 -5
- package/dist/next/index.d.mts.map +1 -1
- package/dist/next/index.mjs +36 -38
- package/dist/next/index.mjs.map +1 -1
- package/dist/next/instrumentation.d.mts +1 -1
- package/dist/next/instrumentation.mjs +1 -1
- package/dist/next/instrumentation.mjs.map +1 -1
- package/dist/nitro/errorHandler.mjs +10 -16
- package/dist/nitro/errorHandler.mjs.map +1 -1
- package/dist/nitro/module.d.mts +2 -2
- package/dist/nitro/module.d.mts.map +1 -1
- package/dist/nitro/module.mjs +8 -2
- package/dist/nitro/module.mjs.map +1 -1
- package/dist/nitro/plugin.mjs +37 -65
- package/dist/nitro/plugin.mjs.map +1 -1
- package/dist/nitro/v3/errorHandler.d.mts +0 -7
- package/dist/nitro/v3/errorHandler.mjs +13 -15
- package/dist/nitro/v3/errorHandler.mjs.map +1 -1
- package/dist/nitro/v3/index.d.mts +2 -2
- package/dist/nitro/v3/module.d.mts +1 -1
- package/dist/nitro/v3/module.d.mts.map +1 -1
- package/dist/nitro/v3/module.mjs +9 -4
- package/dist/nitro/v3/module.mjs.map +1 -1
- package/dist/nitro/v3/plugin.mjs +77 -44
- package/dist/nitro/v3/plugin.mjs.map +1 -1
- package/dist/nitro/v3/useLogger.d.mts +1 -1
- package/dist/nitro-ClRZLD1g.mjs +96 -0
- package/dist/nitro-ClRZLD1g.mjs.map +1 -0
- package/dist/{nitro-oZre8ab3.d.mts → nitro-zCXTylj4.d.mts} +7 -2
- package/dist/nitro-zCXTylj4.d.mts.map +1 -0
- package/dist/nitroConfigBridge-BkVWnSV3.mjs +164 -0
- package/dist/nitroConfigBridge-BkVWnSV3.mjs.map +1 -0
- package/dist/{nodeResponse-BkkionWl.mjs → nodeResponse-CIEEbrNE.mjs} +1 -1
- package/dist/{nodeResponse-BkkionWl.mjs.map → nodeResponse-CIEEbrNE.mjs.map} +1 -1
- package/dist/nuxt/module.d.mts +13 -4
- package/dist/nuxt/module.d.mts.map +1 -1
- package/dist/nuxt/module.mjs +11 -4
- package/dist/nuxt/module.mjs.map +1 -1
- package/dist/orpc/index.d.mts +115 -0
- package/dist/orpc/index.d.mts.map +1 -0
- package/dist/orpc/index.mjs +145 -0
- package/dist/orpc/index.mjs.map +1 -0
- package/dist/{package-v_MmOZeA.mjs → package-CUhII9DA.mjs} +2 -2
- package/dist/package-CUhII9DA.mjs.map +1 -0
- package/dist/{parseError-yVZ58wIK.d.mts → parseError-Cagr-Ctc.d.mts} +2 -2
- package/dist/parseError-Cagr-Ctc.d.mts.map +1 -0
- package/dist/pretty-error-CVVgwlTn.mjs +278 -0
- package/dist/pretty-error-CVVgwlTn.mjs.map +1 -0
- package/dist/pretty-error-snippet.node-c_bzjg7g.mjs +47 -0
- package/dist/pretty-error-snippet.node-c_bzjg7g.mjs.map +1 -0
- package/dist/react-router/index.d.mts +2 -2
- package/dist/react-router/index.mjs +5 -6
- package/dist/react-router/index.mjs.map +1 -1
- package/dist/{routes-CnIgYWf8.mjs → routes-4rMzRyTk.mjs} +1 -1
- package/dist/{routes-CnIgYWf8.mjs.map → routes-4rMzRyTk.mjs.map} +1 -1
- package/dist/runtime/client/log.d.mts +1 -1
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs +28 -12
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
- package/dist/runtime/server/useLogger.d.mts +1 -1
- package/dist/runtime/utils/parseError.d.mts +2 -2
- package/dist/runtime/utils/parseError.mjs +1 -1
- package/dist/{severity-R5Egq3qz.mjs → severity-CwXUSHt3.mjs} +1 -1
- package/dist/{severity-R5Egq3qz.mjs.map → severity-CwXUSHt3.mjs.map} +1 -1
- package/dist/{source-location-Dco0cRTz.mjs → source-location-xkDGiERl.mjs} +1 -1
- package/dist/{source-location-Dco0cRTz.mjs.map → source-location-xkDGiERl.mjs.map} +1 -1
- package/dist/{storage-Dwinmg8P.mjs → storage-7X37OToT.mjs} +2 -1
- package/dist/{storage-Dwinmg8P.mjs.map → storage-7X37OToT.mjs.map} +1 -1
- package/dist/stream.d.mts +1 -1
- package/dist/stream.mjs +1 -1
- package/dist/streamResponse-CmQ3qUbF.mjs +94 -0
- package/dist/streamResponse-CmQ3qUbF.mjs.map +1 -0
- package/dist/sveltekit/index.d.mts +3 -3
- package/dist/sveltekit/index.d.mts.map +1 -1
- package/dist/sveltekit/index.mjs +48 -16
- package/dist/sveltekit/index.mjs.map +1 -1
- package/dist/toolkit.d.mts +38 -7
- package/dist/toolkit.d.mts.map +1 -1
- package/dist/toolkit.mjs +15 -14
- package/dist/types.d.mts +2 -2
- package/dist/{useLogger-BsPL4AQm.d.mts → useLogger-Dv52PDpH.d.mts} +2 -2
- package/dist/{useLogger-BsPL4AQm.d.mts.map → useLogger-Dv52PDpH.d.mts.map} +1 -1
- package/dist/{utils-DLCeShxL.d.mts → utils-DmNbZwBZ.d.mts} +21 -4
- package/dist/{utils-DLCeShxL.d.mts.map → utils-DmNbZwBZ.d.mts.map} +1 -1
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +31 -9
- package/dist/utils.mjs.map +1 -1
- package/dist/vite/index.d.mts +1 -1
- package/dist/vite/index.mjs +1 -1
- package/dist/workers.d.mts +1 -1
- package/dist/workers.mjs +1 -1
- package/package.json +48 -15
- package/dist/audit-CC8nfazi.d.mts.map +0 -1
- package/dist/audit-pV5aLGP0.mjs.map +0 -1
- package/dist/define-D6OJdSUH.mjs.map +0 -1
- package/dist/define-MSdhzmXn.d.mts.map +0 -1
- package/dist/drain-X7_5szSI.mjs.map +0 -1
- package/dist/fork-8u_zFOJq.mjs.map +0 -1
- package/dist/index-o1_z4phv.d.mts.map +0 -1
- package/dist/logger-DntcxxHg.d.mts.map +0 -1
- package/dist/middleware-U-lIAzHg.d.mts.map +0 -1
- package/dist/nitro-DErMq_Zj.mjs +0 -34
- package/dist/nitro-DErMq_Zj.mjs.map +0 -1
- package/dist/nitro-oZre8ab3.d.mts.map +0 -1
- package/dist/nitroConfigBridge-DKk7eOn-.mjs +0 -92
- package/dist/nitroConfigBridge-DKk7eOn-.mjs.map +0 -1
- package/dist/package-v_MmOZeA.mjs.map +0 -1
- package/dist/parseError-yVZ58wIK.d.mts.map +0 -1
package/dist/nuxt/module.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as RedactConfig, H as EnvironmentContext, X as LogLevel, at as RouteConfig, dt as TransportConfig, ot as SamplingConfig, pt as DevTerminalInput } from "../audit-BUAajsPU.mjs";
|
|
2
2
|
import { StreamServerOptions } from "../stream.mjs";
|
|
3
3
|
import * as _$_nuxt_schema0 from "@nuxt/schema";
|
|
4
4
|
|
|
@@ -6,8 +6,12 @@ import * as _$_nuxt_schema0 from "@nuxt/schema";
|
|
|
6
6
|
interface ModuleAxiomBaseConfig {
|
|
7
7
|
/** Axiom dataset name */
|
|
8
8
|
dataset: string;
|
|
9
|
-
/** Axiom API token */
|
|
10
|
-
|
|
9
|
+
/** Axiom API token (evlog field `apiKey`) */
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Renamed to `apiKey`. Will be removed in the next major version.
|
|
13
|
+
*/
|
|
14
|
+
token?: string;
|
|
11
15
|
/** Organization ID (required for Personal Access Tokens) */
|
|
12
16
|
orgId?: string;
|
|
13
17
|
/** Request timeout in milliseconds. Default: 5000 */
|
|
@@ -53,6 +57,11 @@ interface ModuleOptions {
|
|
|
53
57
|
* @default true in development, false in production
|
|
54
58
|
*/
|
|
55
59
|
pretty?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Dev terminal output: preset or explicit overlay + pretty-error settings.
|
|
62
|
+
* @default 'evlog' when pretty in development
|
|
63
|
+
*/
|
|
64
|
+
dev?: DevTerminalInput;
|
|
56
65
|
/**
|
|
57
66
|
* Suppress built-in console output.
|
|
58
67
|
* When true, events are still built, sampled, and passed to drains,
|
|
@@ -159,7 +168,7 @@ interface ModuleOptions {
|
|
|
159
168
|
* ```ts
|
|
160
169
|
* axiom: {
|
|
161
170
|
* dataset: 'my-app-logs',
|
|
162
|
-
*
|
|
171
|
+
* apiKey: process.env.AXIOM_API_KEY,
|
|
163
172
|
* }
|
|
164
173
|
* ```
|
|
165
174
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.mts","names":[],"sources":["../../src/nuxt/module.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"module.d.mts","names":[],"sources":["../../src/nuxt/module.ts"],"mappings":";;;;;UAkBU,qBAAA;;EAER,OAAA;EAFQ;EAIR,MAAA;;;;EAIA,KAAA;EAAA;EAEA,KAAA;EAEA;EAAA,OAAA;AAAA;AAAA,UAGQ,qBAAA;EAAqB;;;;AAQtB;EAFP,OAAA;;EAEA,OAAA;AAAA;AAAA,UAGQ,yBAAA;EAOY;EALpB,OAAA;EAKuB;EAHvB,OAAA;AAAA;AAAA,KAGG,iBAAA,GAAoB,qBAAA,IAAyB,qBAAA,GAAwB,yBAAA;AAAA,UAEzD,aAAA;EAFQ;;;;;EAQvB,OAAA;EAN4B;;;EAW5B,GAAA,GAAM,OAAA,CAAQ,kBAAA;EAoBR;;;;;;EAZN,OAAA;EAoIQ;;;;EA9HR,MAAA;EAgOQ;;;;EA1NR,GAAA,GAAM,gBAAA;EApBA;;;;;;;EA6BN,MAAA;EAgBA;;;;;;EARA,OAAA;EAgDW;;;;;;EAxCX,OAAA;EA+GA;;;;;;;;;;;;;EAhGA,MAAA,GAAS,MAAA,SAAe,WAAA;EAiJtB;;;;;;;;;;;;;AAiDH;;;EAhLC,QAAA,GAAW,cAAA;;;;;;EAOX,QAAA,GAAW,QAAA;;;;;;;;;;;;;EAcX,SAAA,GAAY,eAAA;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BZ,MAAA,aA3B2B,mBAAA;;;;;;;;;;;;;EAyC3B,KAAA,GAAQ,iBAAA;;;;;;;;;;;;;;;EAgBR,IAAA;2DAEE,QAAA;IAEA,WAAA;IAEA,kBAAA,GAAqB,MAAA;IAErB,OAAA,GAAU,MAAA;IAEV,OAAA;EAAA;;;;;;;;;;;;;EAeF,OAAA;kCAEE,MAAA;IAEA,IAAA;IAEA,OAAA;EAAA;;;;;;;;;;;;EAcF,MAAA;qBAEE,GAAA;IAEA,WAAA;IAEA,OAAA;IAEA,IAAA,GAAO,MAAA;IAEP,OAAA;EAAA;;;;;;;;;;;;;;;;;;;EAqBF,MAAA,aAAmB,YAAA;;;;;EAMnB,KAAA,GAAQ,QAAA;;;;;;;EAQR,cAAA;;;;;;EAOA,SAAA;AAAA;AAAA,cACD,QAAA"}
|
package/dist/nuxt/module.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as
|
|
1
|
+
import { r as prependNitroErrorHandler } from "../nitro-ClRZLD1g.mjs";
|
|
2
|
+
import { n as createStripPlugin, t as createSourceLocationPlugin } from "../source-location-xkDGiERl.mjs";
|
|
3
|
+
import { n as version, t as name } from "../package-CUhII9DA.mjs";
|
|
3
4
|
import { addImports, addPlugin, addServerHandler, addServerImports, addServerPlugin, addVitePlugin, createResolver, defineNuxtModule } from "@nuxt/kit";
|
|
4
5
|
//#region src/nuxt/module.ts
|
|
5
6
|
var module_default = defineNuxtModule({
|
|
@@ -21,9 +22,15 @@ var module_default = defineNuxtModule({
|
|
|
21
22
|
options.stream = normalizedStream;
|
|
22
23
|
nuxt.options.runtimeConfig.evlog = options;
|
|
23
24
|
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
24
|
-
|
|
25
|
+
const evlogHandler = resolver.resolve("../nitro/errorHandler").replace(/\\/g, "/");
|
|
26
|
+
nitroConfig.errorHandler = prependNitroErrorHandler(nitroConfig.errorHandler, evlogHandler);
|
|
25
27
|
const evlogForNitro = nuxt.options.runtimeConfig.evlog ?? options;
|
|
26
|
-
if (evlogForNitro !== void 0 && typeof evlogForNitro === "object")
|
|
28
|
+
if (evlogForNitro !== void 0 && typeof evlogForNitro === "object") {
|
|
29
|
+
const serialized = JSON.stringify(evlogForNitro);
|
|
30
|
+
nitroConfig.replace = nitroConfig.replace || {};
|
|
31
|
+
nitroConfig.replace.__EVLOG_CONFIG__ = serialized;
|
|
32
|
+
process.env.__EVLOG_CONFIG = serialized;
|
|
33
|
+
}
|
|
27
34
|
});
|
|
28
35
|
nuxt.options.runtimeConfig.public.evlog = {
|
|
29
36
|
enabled: options.enabled ?? true,
|
package/dist/nuxt/module.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.mjs","names":[],"sources":["../../src/nuxt/module.ts"],"sourcesContent":["import {\n addImports,\n addPlugin,\n addServerHandler,\n addServerImports,\n addServerPlugin,\n addVitePlugin,\n createResolver,\n defineNuxtModule,\n} from '@nuxt/kit'\nimport type { NitroConfig } from 'nitropack'\nimport type { EnvironmentContext, LogLevel, RedactConfig, RouteConfig, SamplingConfig, TransportConfig } from '../types'\nimport { createStripPlugin } from '../vite/strip'\nimport { createSourceLocationPlugin } from '../vite/source-location'\nimport { name, version } from '../../package.json'\n\ninterface ModuleAxiomBaseConfig {\n /** Axiom dataset name */\n dataset: string\n /** Axiom API token */\n token: string\n /** Organization ID (required for Personal Access Tokens) */\n orgId?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n}\n\ninterface ModuleAxiomEdgeConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface ModuleAxiomEndpointConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\ntype ModuleAxiomConfig = ModuleAxiomBaseConfig & (ModuleAxiomEdgeConfig | ModuleAxiomEndpointConfig)\n\nexport interface ModuleOptions {\n /**\n * Enable or disable all logging globally.\n * When false, all emits, tagged logs, and request logger operations become no-ops.\n * @default true\n */\n enabled?: boolean\n\n /**\n * Environment context overrides.\n */\n env?: Partial<EnvironmentContext>\n\n /**\n * Enable or disable browser console output.\n * When false, client-side logs are suppressed in the browser DevTools console\n * but still sent to the server via transport (if enabled).\n * @default true\n */\n console?: boolean\n\n /**\n * Enable pretty printing.\n * @default true in development, false in production\n */\n pretty?: boolean\n\n /**\n * Suppress built-in console output.\n * When true, events are still built, sampled, and passed to drains,\n * but nothing is written to console. Use when drains own the output\n * channel (e.g., stdout-based platforms like GCP Cloud Run, AWS Lambda).\n * @default false\n */\n silent?: boolean\n\n /**\n * Route patterns to include in logging.\n * Supports glob patterns like '/api/**'.\n * If not set, all routes are logged.\n * @example ['/api/**', '/auth/**']\n */\n include?: string[]\n\n /**\n * Route patterns to exclude from logging.\n * Supports glob patterns like '/api/_nuxt_icon/**'.\n * Exclusions take precedence over inclusions.\n * @example ['/api/_nuxt_icon/**', '/health']\n */\n exclude?: string[]\n\n /**\n * Route-specific service configuration.\n * Allows setting different service names for different routes.\n * Patterns are matched using glob syntax.\n *\n * @example\n * ```ts\n * routes: {\n * '/api/foo/**': { service: 'service1' },\n * '/api/bar/**': { service: 'service2' }\n * }\n * ```\n */\n routes?: Record<string, RouteConfig>\n\n /**\n * Sampling configuration for filtering logs.\n * Allows configuring what percentage of logs to keep per level.\n *\n * @example\n * ```ts\n * sampling: {\n * rates: {\n * info: 10, // Keep 10% of info logs\n * warn: 50, // Keep 50% of warning logs\n * debug: 5, // Keep 5% of debug logs\n * error: 100, // Always keep errors (default)\n * }\n * }\n * ```\n */\n sampling?: SamplingConfig\n\n /**\n * Minimum severity for the global `log` API on server and client (not request wide events).\n * Order: debug < info < warn < error.\n * @default 'debug'\n */\n minLevel?: LogLevel\n\n /**\n * Transport configuration for sending client logs to the server.\n *\n * @example\n * ```ts\n * transport: {\n * enabled: true, // send client logs to server via API endpoint\n * endpoint: '/api/_evlog/ingest', // default endpoint (or custom endpoint)\n * credentials: 'include', // optional: cross-origin ingest\n * }\n * ```\n */\n transport?: TransportConfig\n\n /**\n * Live stream of wide events, exposed by a small local HTTP server on\n * an ephemeral port. Any consumer (browser tab, CLI, devtool) can\n * subscribe via Server-Sent Events. The URL is printed at startup and\n * written to `.evlog/stream.url`.\n *\n * Strict opt-in — nothing starts unless this is set.\n *\n * - `true` — enable with defaults\n * - `false` — off (same as omitting)\n * - `StreamServerOptions` — full config (port, host, token, ...)\n * - `undefined` (default) — off\n *\n * Local-only: binds to `127.0.0.1` and does not work on serverless\n * platforms (each invocation is isolated).\n *\n * @example\n * ```ts\n * // Enable with defaults\n * evlog: { stream: true }\n *\n * // Custom port + auth token\n * evlog: { stream: { port: 4317, token: process.env.EVLOG_STREAM_TOKEN } }\n * ```\n */\n stream?: boolean | import('../stream').StreamServerOptions\n\n /**\n * Axiom adapter configuration.\n * When configured, use `createAxiomDrain()` from `evlog/axiom` to send logs.\n *\n * @example\n * ```ts\n * axiom: {\n * dataset: 'my-app-logs',\n * token: process.env.AXIOM_TOKEN,\n * }\n * ```\n */\n axiom?: ModuleAxiomConfig\n\n /**\n * OTLP adapter configuration.\n * When configured, use `createOTLPDrain()` from `evlog/otlp` to send logs.\n *\n * @example\n * ```ts\n * otlp: {\n * endpoint: 'http://localhost:4318',\n * headers: {\n * 'Authorization': `Basic ${process.env.GRAFANA_TOKEN}`,\n * },\n * }\n * ```\n */\n otlp?: {\n /** OTLP HTTP endpoint (e.g., http://localhost:4318) */\n endpoint: string\n /** Override service name (defaults to event.service) */\n serviceName?: string\n /** Additional resource attributes */\n resourceAttributes?: Record<string, string | number | boolean>\n /** Custom headers (e.g., for authentication) */\n headers?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * PostHog adapter configuration.\n * When configured, use `createPostHogDrain()` from `evlog/posthog` to send logs\n * via PostHog Logs (OTLP).\n *\n * @example\n * ```ts\n * posthog: {\n * apiKey: process.env.POSTHOG_API_KEY,\n * }\n * ```\n */\n posthog?: {\n /** PostHog project API key */\n apiKey: string\n /** PostHog host URL. Default: https://us.i.posthog.com */\n host?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Sentry adapter configuration.\n * When configured, use `createSentryDrain()` from `evlog/sentry` to send logs.\n *\n * @example\n * ```ts\n * sentry: {\n * dsn: process.env.SENTRY_DSN,\n * }\n * ```\n */\n sentry?: {\n /** Sentry DSN */\n dsn: string\n /** Environment override (defaults to event.environment) */\n environment?: string\n /** Release version override (defaults to event.version) */\n release?: string\n /** Additional tags to attach as attributes */\n tags?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Auto-redaction configuration for PII protection.\n * `true` enables all built-in PII patterns (email, credit card, IPv4, phone, SSN).\n * Pass an object for fine-grained control.\n *\n * @example\n * ```ts\n * // Enable all built-in PII patterns\n * evlog: { redact: true }\n *\n * // Add custom paths on top of built-ins\n * evlog: {\n * redact: {\n * paths: ['user.password', 'headers.authorization'],\n * }\n * }\n * ```\n */\n redact?: boolean | RedactConfig\n\n /**\n * Log levels to strip from production builds. Set to [] to disable.\n * @default ['debug']\n */\n strip?: LogLevel[]\n\n /**\n * Inject source file:line into log calls.\n * When true, active in both dev and prod.\n * When 'dev', active only in development.\n * @default 'dev'\n */\n sourceLocation?: boolean | 'dev'\n\n /**\n * How long to retain events before cleanup (used by @evlog/nuxthub).\n * Supports \"30d\" (days), \"24h\" (hours), \"60m\" (minutes).\n * @default '30d'\n */\n retention?: string\n}\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name,\n version,\n configKey: name,\n docs: 'https://evlog.dev',\n },\n defaults: {},\n setup(options, nuxt) {\n const resolver = createResolver(import.meta.url)\n\n const transportEnabled = options.transport?.enabled ?? false\n const transportEndpoint = options.transport?.endpoint ?? '/api/_evlog/ingest'\n const transportCredentials = options.transport?.credentials ?? 'same-origin'\n\n // Normalize `evlog.stream` into a single canonical shape so the Nitro\n // plugin (which reads runtimeConfig.evlog at server boot) sees a\n // consistent value.\n //\n // The stream is exposed by a separate mini HTTP server on its own\n // ephemeral port (see `evlog/stream` → `startStreamServer`). It does\n // NOT register a route in the user's app.\n //\n // Strict opt-in: nothing starts unless the user explicitly asks for it.\n // - `stream === true` → enabled with defaults\n // - `stream === false` → off (alias for undefined)\n // - `stream: { ... }` → enabled with user options\n // - `stream === undefined` → off\n const streamRaw = options.stream\n const normalizedStream\n = streamRaw === true\n ? true\n : streamRaw && typeof streamRaw === 'object'\n ? streamRaw\n : false\n const streamEnabled = normalizedStream !== false\n options.stream = normalizedStream\n\n nuxt.options.runtimeConfig.evlog = options\n\n // Register custom error handler for proper EvlogError serialization\n // Only set if not already configured to avoid overwriting user's custom handler\n // Mirror standalone Nitro modules: serialize evlog options into __EVLOG_CONFIG so\n // resolveEvlogConfigForNitroPlugin() picks them up in dev (Nitro worker threads\n // often cannot resolve useRuntimeConfig().evlog via dynamic import reliably).\n // @ts-expect-error nitro:config hook exists but is not in NuxtHooks type\n nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {\n nitroConfig.errorHandler = nitroConfig.errorHandler || resolver.resolve('../nitro/errorHandler')\n\n const evlogForNitro = nuxt.options.runtimeConfig.evlog ?? options\n if (evlogForNitro !== undefined && typeof evlogForNitro === 'object') {\n process.env.__EVLOG_CONFIG = JSON.stringify(evlogForNitro)\n }\n })\n nuxt.options.runtimeConfig.public.evlog = {\n enabled: options.enabled ?? true,\n console: options.console,\n pretty: options.pretty,\n minLevel: options.minLevel,\n transport: {\n enabled: transportEnabled,\n endpoint: transportEndpoint,\n credentials: transportCredentials,\n },\n }\n\n if (transportEnabled) {\n addServerHandler({\n route: transportEndpoint,\n method: 'post',\n handler: resolver.resolve('../runtime/server/routes/_evlog/ingest.post'),\n })\n }\n\n if (streamEnabled) {\n // The stream itself is served by an out-of-band HTTP mini-server\n // started in the Nitro plugin — see startStreamServer() in\n // packages/evlog/src/stream.ts. Here we only register a discovery\n // route so a browser tab on the user's app can find the mini-server\n // URL without having to read `.evlog/stream.url` directly.\n addServerHandler({\n route: '/api/_evlog/stream-info',\n method: 'get',\n handler: resolver.resolve('../runtime/server/routes/_evlog/stream-info.get'),\n })\n }\n\n addServerPlugin(resolver.resolve('../nitro/plugin'))\n\n addPlugin({\n src: resolver.resolve('../runtime/client/plugin'),\n mode: 'client',\n })\n\n addImports([\n {\n name: 'log',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'clearIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setMinLevel',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n {\n name: 'parseError',\n from: resolver.resolve('../runtime/utils/parseError'),\n },\n ])\n\n addServerImports([\n {\n name: 'useLogger',\n from: resolver.resolve('../runtime/server/useLogger'),\n },\n {\n name: 'log',\n from: resolver.resolve('../logger'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n ])\n\n const stripLevels = options.strip ?? ['debug']\n if (stripLevels.length > 0) {\n addVitePlugin(createStripPlugin(stripLevels))\n }\n\n const srcLoc = options.sourceLocation ?? 'dev'\n if (srcLoc === true || (srcLoc === 'dev' && nuxt.options.dev)) {\n addVitePlugin(createSourceLocationPlugin(true))\n }\n },\n})\n"],"mappings":";;;;AAoTA,IAAA,iBAAe,iBAAgC;CAC7C,MAAM;EACJ;EACA;EACA,WAAW;EACX,MAAM;EACP;CACD,UAAU,EAAE;CACZ,MAAM,SAAS,MAAM;EACnB,MAAM,WAAW,eAAe,OAAO,KAAK,IAAI;EAEhD,MAAM,mBAAmB,QAAQ,WAAW,WAAW;EACvD,MAAM,oBAAoB,QAAQ,WAAW,YAAY;EACzD,MAAM,uBAAuB,QAAQ,WAAW,eAAe;EAe/D,MAAM,YAAY,QAAQ;EAC1B,MAAM,mBACF,cAAc,OACZ,OACA,aAAa,OAAO,cAAc,WAChC,YACA;EACR,MAAM,gBAAgB,qBAAqB;AAC3C,UAAQ,SAAS;AAEjB,OAAK,QAAQ,cAAc,QAAQ;AAQnC,OAAK,KAAK,iBAAiB,gBAA6B;AACtD,eAAY,eAAe,YAAY,gBAAgB,SAAS,QAAQ,wBAAwB;GAEhG,MAAM,gBAAgB,KAAK,QAAQ,cAAc,SAAS;AAC1D,OAAI,kBAAkB,KAAA,KAAa,OAAO,kBAAkB,SAC1D,SAAQ,IAAI,iBAAiB,KAAK,UAAU,cAAc;IAE5D;AACF,OAAK,QAAQ,cAAc,OAAO,QAAQ;GACxC,SAAS,QAAQ,WAAW;GAC5B,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,WAAW;IACT,SAAS;IACT,UAAU;IACV,aAAa;IACd;GACF;AAED,MAAI,iBACF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,8CAA8C;GACzE,CAAC;AAGJ,MAAI,cAMF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,kDAAkD;GAC7E,CAAC;AAGJ,kBAAgB,SAAS,QAAQ,kBAAkB,CAAC;AAEpD,YAAU;GACR,KAAK,SAAS,QAAQ,2BAA2B;GACjD,MAAM;GACP,CAAC;AAEF,aAAW;GACT;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACF,CAAC;AAEF,mBAAiB;GACf;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,YAAY;IACpC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACF,CAAC;EAEF,MAAM,cAAc,QAAQ,SAAS,CAAC,QAAQ;AAC9C,MAAI,YAAY,SAAS,EACvB,eAAc,kBAAkB,YAAY,CAAC;EAG/C,MAAM,SAAS,QAAQ,kBAAkB;AACzC,MAAI,WAAW,QAAS,WAAW,SAAS,KAAK,QAAQ,IACvD,eAAc,2BAA2B,KAAK,CAAC;;CAGpD,CAAC"}
|
|
1
|
+
{"version":3,"file":"module.mjs","names":[],"sources":["../../src/nuxt/module.ts"],"sourcesContent":["import {\n addImports,\n addPlugin,\n addServerHandler,\n addServerImports,\n addServerPlugin,\n addVitePlugin,\n createResolver,\n defineNuxtModule,\n} from '@nuxt/kit'\nimport type { NitroConfig } from 'nitropack'\nimport type { EnvironmentContext, LogLevel, RedactConfig, RouteConfig, SamplingConfig, TransportConfig } from '../types'\nimport type { DevTerminalInput } from '../shared/dev-terminal'\nimport { prependNitroErrorHandler } from '../nitro'\nimport { createStripPlugin } from '../vite/strip'\nimport { createSourceLocationPlugin } from '../vite/source-location'\nimport { name, version } from '../../package.json'\n\ninterface ModuleAxiomBaseConfig {\n /** Axiom dataset name */\n dataset: string\n /** Axiom API token (evlog field `apiKey`) */\n apiKey?: string\n /**\n * @deprecated Renamed to `apiKey`. Will be removed in the next major version.\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}\n\ninterface ModuleAxiomEdgeConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface ModuleAxiomEndpointConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\ntype ModuleAxiomConfig = ModuleAxiomBaseConfig & (ModuleAxiomEdgeConfig | ModuleAxiomEndpointConfig)\n\nexport interface ModuleOptions {\n /**\n * Enable or disable all logging globally.\n * When false, all emits, tagged logs, and request logger operations become no-ops.\n * @default true\n */\n enabled?: boolean\n\n /**\n * Environment context overrides.\n */\n env?: Partial<EnvironmentContext>\n\n /**\n * Enable or disable browser console output.\n * When false, client-side logs are suppressed in the browser DevTools console\n * but still sent to the server via transport (if enabled).\n * @default true\n */\n console?: boolean\n\n /**\n * Enable pretty printing.\n * @default true in development, false in production\n */\n pretty?: boolean\n\n /**\n * Dev terminal output: preset or explicit overlay + pretty-error settings.\n * @default 'evlog' when pretty in development\n */\n dev?: DevTerminalInput\n\n /**\n * Suppress built-in console output.\n * When true, events are still built, sampled, and passed to drains,\n * but nothing is written to console. Use when drains own the output\n * channel (e.g., stdout-based platforms like GCP Cloud Run, AWS Lambda).\n * @default false\n */\n silent?: boolean\n\n /**\n * Route patterns to include in logging.\n * Supports glob patterns like '/api/**'.\n * If not set, all routes are logged.\n * @example ['/api/**', '/auth/**']\n */\n include?: string[]\n\n /**\n * Route patterns to exclude from logging.\n * Supports glob patterns like '/api/_nuxt_icon/**'.\n * Exclusions take precedence over inclusions.\n * @example ['/api/_nuxt_icon/**', '/health']\n */\n exclude?: string[]\n\n /**\n * Route-specific service configuration.\n * Allows setting different service names for different routes.\n * Patterns are matched using glob syntax.\n *\n * @example\n * ```ts\n * routes: {\n * '/api/foo/**': { service: 'service1' },\n * '/api/bar/**': { service: 'service2' }\n * }\n * ```\n */\n routes?: Record<string, RouteConfig>\n\n /**\n * Sampling configuration for filtering logs.\n * Allows configuring what percentage of logs to keep per level.\n *\n * @example\n * ```ts\n * sampling: {\n * rates: {\n * info: 10, // Keep 10% of info logs\n * warn: 50, // Keep 50% of warning logs\n * debug: 5, // Keep 5% of debug logs\n * error: 100, // Always keep errors (default)\n * }\n * }\n * ```\n */\n sampling?: SamplingConfig\n\n /**\n * Minimum severity for the global `log` API on server and client (not request wide events).\n * Order: debug < info < warn < error.\n * @default 'debug'\n */\n minLevel?: LogLevel\n\n /**\n * Transport configuration for sending client logs to the server.\n *\n * @example\n * ```ts\n * transport: {\n * enabled: true, // send client logs to server via API endpoint\n * endpoint: '/api/_evlog/ingest', // default endpoint (or custom endpoint)\n * credentials: 'include', // optional: cross-origin ingest\n * }\n * ```\n */\n transport?: TransportConfig\n\n /**\n * Live stream of wide events, exposed by a small local HTTP server on\n * an ephemeral port. Any consumer (browser tab, CLI, devtool) can\n * subscribe via Server-Sent Events. The URL is printed at startup and\n * written to `.evlog/stream.url`.\n *\n * Strict opt-in — nothing starts unless this is set.\n *\n * - `true` — enable with defaults\n * - `false` — off (same as omitting)\n * - `StreamServerOptions` — full config (port, host, token, ...)\n * - `undefined` (default) — off\n *\n * Local-only: binds to `127.0.0.1` and does not work on serverless\n * platforms (each invocation is isolated).\n *\n * @example\n * ```ts\n * // Enable with defaults\n * evlog: { stream: true }\n *\n * // Custom port + auth token\n * evlog: { stream: { port: 4317, token: process.env.EVLOG_STREAM_TOKEN } }\n * ```\n */\n stream?: boolean | import('../stream').StreamServerOptions\n\n /**\n * Axiom adapter configuration.\n * When configured, use `createAxiomDrain()` from `evlog/axiom` to send logs.\n *\n * @example\n * ```ts\n * axiom: {\n * dataset: 'my-app-logs',\n * apiKey: process.env.AXIOM_API_KEY,\n * }\n * ```\n */\n axiom?: ModuleAxiomConfig\n\n /**\n * OTLP adapter configuration.\n * When configured, use `createOTLPDrain()` from `evlog/otlp` to send logs.\n *\n * @example\n * ```ts\n * otlp: {\n * endpoint: 'http://localhost:4318',\n * headers: {\n * 'Authorization': `Basic ${process.env.GRAFANA_TOKEN}`,\n * },\n * }\n * ```\n */\n otlp?: {\n /** OTLP HTTP endpoint (e.g., http://localhost:4318) */\n endpoint: string\n /** Override service name (defaults to event.service) */\n serviceName?: string\n /** Additional resource attributes */\n resourceAttributes?: Record<string, string | number | boolean>\n /** Custom headers (e.g., for authentication) */\n headers?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * PostHog adapter configuration.\n * When configured, use `createPostHogDrain()` from `evlog/posthog` to send logs\n * via PostHog Logs (OTLP).\n *\n * @example\n * ```ts\n * posthog: {\n * apiKey: process.env.POSTHOG_API_KEY,\n * }\n * ```\n */\n posthog?: {\n /** PostHog project API key */\n apiKey: string\n /** PostHog host URL. Default: https://us.i.posthog.com */\n host?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Sentry adapter configuration.\n * When configured, use `createSentryDrain()` from `evlog/sentry` to send logs.\n *\n * @example\n * ```ts\n * sentry: {\n * dsn: process.env.SENTRY_DSN,\n * }\n * ```\n */\n sentry?: {\n /** Sentry DSN */\n dsn: string\n /** Environment override (defaults to event.environment) */\n environment?: string\n /** Release version override (defaults to event.version) */\n release?: string\n /** Additional tags to attach as attributes */\n tags?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Auto-redaction configuration for PII protection.\n * `true` enables all built-in PII patterns (email, credit card, IPv4, phone, SSN).\n * Pass an object for fine-grained control.\n *\n * @example\n * ```ts\n * // Enable all built-in PII patterns\n * evlog: { redact: true }\n *\n * // Add custom paths on top of built-ins\n * evlog: {\n * redact: {\n * paths: ['user.password', 'headers.authorization'],\n * }\n * }\n * ```\n */\n redact?: boolean | RedactConfig\n\n /**\n * Log levels to strip from production builds. Set to [] to disable.\n * @default ['debug']\n */\n strip?: LogLevel[]\n\n /**\n * Inject source file:line into log calls.\n * When true, active in both dev and prod.\n * When 'dev', active only in development.\n * @default 'dev'\n */\n sourceLocation?: boolean | 'dev'\n\n /**\n * How long to retain events before cleanup (used by @evlog/nuxthub).\n * Supports \"30d\" (days), \"24h\" (hours), \"60m\" (minutes).\n * @default '30d'\n */\n retention?: string\n}\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name,\n version,\n configKey: name,\n docs: 'https://evlog.dev',\n },\n defaults: {},\n setup(options, nuxt) {\n const resolver = createResolver(import.meta.url)\n\n const transportEnabled = options.transport?.enabled ?? false\n const transportEndpoint = options.transport?.endpoint ?? '/api/_evlog/ingest'\n const transportCredentials = options.transport?.credentials ?? 'same-origin'\n\n // Normalize `evlog.stream` into a single canonical shape so the Nitro\n // plugin (which reads runtimeConfig.evlog at server boot) sees a\n // consistent value.\n //\n // The stream is exposed by a separate mini HTTP server on its own\n // ephemeral port (see `evlog/stream` → `startStreamServer`). It does\n // NOT register a route in the user's app.\n //\n // Strict opt-in: nothing starts unless the user explicitly asks for it.\n // - `stream === true` → enabled with defaults\n // - `stream === false` → off (alias for undefined)\n // - `stream: { ... }` → enabled with user options\n // - `stream === undefined` → off\n const streamRaw = options.stream\n const normalizedStream\n = streamRaw === true\n ? true\n : streamRaw && typeof streamRaw === 'object'\n ? streamRaw\n : false\n const streamEnabled = normalizedStream !== false\n options.stream = normalizedStream\n\n nuxt.options.runtimeConfig.evlog = options\n\n // Register custom error handler for proper EvlogError serialization\n // Only set if not already configured to avoid overwriting user's custom handler\n // Mirror standalone Nitro modules: serialize evlog options into __EVLOG_CONFIG so\n // resolveEvlogConfigForNitroPlugin() picks them up in dev (Nitro worker threads\n // often cannot resolve useRuntimeConfig().evlog via dynamic import reliably).\n // @ts-expect-error nitro:config hook exists but is not in NuxtHooks type\n nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {\n const evlogHandler = resolver.resolve('../nitro/errorHandler').replace(/\\\\/g, '/')\n nitroConfig.errorHandler = prependNitroErrorHandler(nitroConfig.errorHandler, evlogHandler)\n\n const evlogForNitro = nuxt.options.runtimeConfig.evlog ?? options\n if (evlogForNitro !== undefined && typeof evlogForNitro === 'object') {\n const serialized = JSON.stringify(evlogForNitro)\n nitroConfig.replace = nitroConfig.replace || {}\n nitroConfig.replace.__EVLOG_CONFIG__ = serialized\n process.env.__EVLOG_CONFIG = serialized\n }\n })\n nuxt.options.runtimeConfig.public.evlog = {\n enabled: options.enabled ?? true,\n console: options.console,\n pretty: options.pretty,\n minLevel: options.minLevel,\n transport: {\n enabled: transportEnabled,\n endpoint: transportEndpoint,\n credentials: transportCredentials,\n },\n }\n\n if (transportEnabled) {\n addServerHandler({\n route: transportEndpoint,\n method: 'post',\n handler: resolver.resolve('../runtime/server/routes/_evlog/ingest.post'),\n })\n }\n\n if (streamEnabled) {\n // The stream itself is served by an out-of-band HTTP mini-server\n // started in the Nitro plugin — see startStreamServer() in\n // packages/evlog/src/stream.ts. Here we only register a discovery\n // route so a browser tab on the user's app can find the mini-server\n // URL without having to read `.evlog/stream.url` directly.\n addServerHandler({\n route: '/api/_evlog/stream-info',\n method: 'get',\n handler: resolver.resolve('../runtime/server/routes/_evlog/stream-info.get'),\n })\n }\n\n addServerPlugin(resolver.resolve('../nitro/plugin'))\n\n addPlugin({\n src: resolver.resolve('../runtime/client/plugin'),\n mode: 'client',\n })\n\n addImports([\n {\n name: 'log',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'clearIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setMinLevel',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n {\n name: 'parseError',\n from: resolver.resolve('../runtime/utils/parseError'),\n },\n ])\n\n addServerImports([\n {\n name: 'useLogger',\n from: resolver.resolve('../runtime/server/useLogger'),\n },\n {\n name: 'log',\n from: resolver.resolve('../logger'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n ])\n\n const stripLevels = options.strip ?? ['debug']\n if (stripLevels.length > 0) {\n addVitePlugin(createStripPlugin(stripLevels))\n }\n\n const srcLoc = options.sourceLocation ?? 'dev'\n if (srcLoc === true || (srcLoc === 'dev' && nuxt.options.dev)) {\n addVitePlugin(createSourceLocationPlugin(true))\n }\n },\n})\n"],"mappings":";;;;;AAgUA,IAAA,iBAAe,iBAAgC;CAC7C,MAAM;EACJ;EACA;EACA,WAAW;EACX,MAAM;EACP;CACD,UAAU,EAAE;CACZ,MAAM,SAAS,MAAM;EACnB,MAAM,WAAW,eAAe,OAAO,KAAK,IAAI;EAEhD,MAAM,mBAAmB,QAAQ,WAAW,WAAW;EACvD,MAAM,oBAAoB,QAAQ,WAAW,YAAY;EACzD,MAAM,uBAAuB,QAAQ,WAAW,eAAe;EAe/D,MAAM,YAAY,QAAQ;EAC1B,MAAM,mBACF,cAAc,OACZ,OACA,aAAa,OAAO,cAAc,WAChC,YACA;EACR,MAAM,gBAAgB,qBAAqB;AAC3C,UAAQ,SAAS;AAEjB,OAAK,QAAQ,cAAc,QAAQ;AAQnC,OAAK,KAAK,iBAAiB,gBAA6B;GACtD,MAAM,eAAe,SAAS,QAAQ,wBAAwB,CAAC,QAAQ,OAAO,IAAI;AAClF,eAAY,eAAe,yBAAyB,YAAY,cAAc,aAAa;GAE3F,MAAM,gBAAgB,KAAK,QAAQ,cAAc,SAAS;AAC1D,OAAI,kBAAkB,KAAA,KAAa,OAAO,kBAAkB,UAAU;IACpE,MAAM,aAAa,KAAK,UAAU,cAAc;AAChD,gBAAY,UAAU,YAAY,WAAW,EAAE;AAC/C,gBAAY,QAAQ,mBAAmB;AACvC,YAAQ,IAAI,iBAAiB;;IAE/B;AACF,OAAK,QAAQ,cAAc,OAAO,QAAQ;GACxC,SAAS,QAAQ,WAAW;GAC5B,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,WAAW;IACT,SAAS;IACT,UAAU;IACV,aAAa;IACd;GACF;AAED,MAAI,iBACF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,8CAA8C;GACzE,CAAC;AAGJ,MAAI,cAMF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,kDAAkD;GAC7E,CAAC;AAGJ,kBAAgB,SAAS,QAAQ,kBAAkB,CAAC;AAEpD,YAAU;GACR,KAAK,SAAS,QAAQ,2BAA2B;GACjD,MAAM;GACP,CAAC;AAEF,aAAW;GACT;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACF,CAAC;AAEF,mBAAiB;GACf;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,YAAY;IACpC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACF,CAAC;EAEF,MAAM,cAAc,QAAQ,SAAS,CAAC,QAAQ;AAC9C,MAAI,YAAY,SAAS,EACvB,eAAc,kBAAkB,YAAY,CAAC;EAG/C,MAAM,SAAS,QAAQ,kBAAkB;AACzC,MAAI,WAAW,QAAS,WAAW,SAAS,KAAK,QAAQ,IACvD,eAAc,2BAA2B,KAAK,CAAC;;CAGpD,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { rt as RequestLogger } from "../audit-BUAajsPU.mjs";
|
|
2
|
+
import { t as BaseEvlogOptions } from "../middleware-DQ6-h8h0.mjs";
|
|
3
|
+
import { Context, MiddlewareOptions, MiddlewareResult } from "@orpc/server";
|
|
4
|
+
|
|
5
|
+
//#region src/orpc/index.d.ts
|
|
6
|
+
declare const useLogger: <T extends object = Record<string, unknown>>() => RequestLogger<T>;
|
|
7
|
+
/** Options accepted by {@link withEvlog} for oRPC request instrumentation. */
|
|
8
|
+
type EvlogOrpcOptions = BaseEvlogOptions;
|
|
9
|
+
/**
|
|
10
|
+
* Inject this type into your oRPC initial context to access `context.log`
|
|
11
|
+
* inside procedures.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { os } from '@orpc/server'
|
|
16
|
+
* import { evlog, type EvlogOrpcContext } from 'evlog/orpc'
|
|
17
|
+
*
|
|
18
|
+
* const base = os.$context<EvlogOrpcContext>().use(evlog())
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
interface EvlogOrpcContext {
|
|
22
|
+
log: RequestLogger;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Result shape of `handler.handle()` for oRPC's fetch adapter
|
|
26
|
+
* ({@link https://orpc.dev/docs/adapters/http RPCHandler / OpenAPIHandler}).
|
|
27
|
+
*/
|
|
28
|
+
type OrpcFetchHandleResult = {
|
|
29
|
+
matched: true;
|
|
30
|
+
response: Response;
|
|
31
|
+
} | {
|
|
32
|
+
matched: false;
|
|
33
|
+
response: undefined;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Minimal subset of oRPC's `FetchHandler` that we need to wrap. Anything
|
|
37
|
+
* compatible (RPCHandler, OpenAPIHandler, custom handler) plugs in.
|
|
38
|
+
*
|
|
39
|
+
* `options` is intentionally typed loosely so this matches both the
|
|
40
|
+
* `(req, opts)` and `(req, opts?)` overloads that oRPC produces depending on
|
|
41
|
+
* whether the router declares a non-empty initial context. The wrapper just
|
|
42
|
+
* splats the original options through and injects `log` into `context`.
|
|
43
|
+
*/
|
|
44
|
+
interface OrpcFetchHandlerLike {
|
|
45
|
+
handle: (request: Request, options?: any) => Promise<OrpcFetchHandleResult>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Wrap an oRPC handler so each matched request emits a single wide event.
|
|
49
|
+
* Works with any handler that exposes `.handle(request, options)` from
|
|
50
|
+
* `@orpc/server/fetch` (RPCHandler, OpenAPIHandler, custom handlers).
|
|
51
|
+
*
|
|
52
|
+
* The returned proxy preserves the original handler's identity (instance
|
|
53
|
+
* methods, plugins, etc.) and only intercepts `handle`. Inside procedures,
|
|
54
|
+
* the request logger is exposed as `context.log` — pair this with
|
|
55
|
+
* `os.use(evlog())` to also accumulate `operation` (`path.join('.')`) on the
|
|
56
|
+
* wide event.
|
|
57
|
+
*
|
|
58
|
+
* Routes that are filtered out by `include`/`exclude` are passed straight to
|
|
59
|
+
* the underlying handler with no instrumentation.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* import { RPCHandler } from '@orpc/server/fetch'
|
|
64
|
+
* import { withEvlog } from 'evlog/orpc'
|
|
65
|
+
* import { router } from './router'
|
|
66
|
+
*
|
|
67
|
+
* const handler = withEvlog(new RPCHandler(router), {
|
|
68
|
+
* include: ['/rpc/**'],
|
|
69
|
+
* })
|
|
70
|
+
*
|
|
71
|
+
* export default async function fetch(request: Request) {
|
|
72
|
+
* const { matched, response } = await handler.handle(request, { prefix: '/rpc' })
|
|
73
|
+
* return matched ? response : new Response('Not Found', { status: 404 })
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function withEvlog<THandler extends OrpcFetchHandlerLike>(handler: THandler, options?: EvlogOrpcOptions): THandler;
|
|
78
|
+
/**
|
|
79
|
+
* Procedure-level middleware. Three responsibilities:
|
|
80
|
+
*
|
|
81
|
+
* 1. Adds `operation` (the procedure path joined by `.`) to the wide event,
|
|
82
|
+
* so consumers can group events by procedure without parsing URLs.
|
|
83
|
+
* 2. Captures errors thrown by the procedure on the wide event so the level
|
|
84
|
+
* is promoted to `error`.
|
|
85
|
+
* 3. Converts {@link EvlogError} (from `createError()` / `defineErrorCatalog`)
|
|
86
|
+
* into a structurally-equivalent {@link ORPCError} before re-throwing, so
|
|
87
|
+
* the wire response carries the catalog `code`, status, message, and the
|
|
88
|
+
* `why` / `fix` / `link` guidance under `data` — instead of being wrapped
|
|
89
|
+
* as `INTERNAL_SERVER_ERROR` by oRPC's default handler. The catalog and
|
|
90
|
+
* `createError()` stay the canonical evlog way to author errors;
|
|
91
|
+
* `evlog/orpc` is the bridge.
|
|
92
|
+
*
|
|
93
|
+
* Requires `withEvlog()` to be wrapped around the handler — the request
|
|
94
|
+
* logger flows in via `context.log`. Declare {@link EvlogOrpcContext} on
|
|
95
|
+
* your oRPC base for typed access.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { os } from '@orpc/server'
|
|
100
|
+
* import { evlog, type EvlogOrpcContext } from 'evlog/orpc'
|
|
101
|
+
*
|
|
102
|
+
* const base = os.$context<EvlogOrpcContext>().use(evlog())
|
|
103
|
+
*
|
|
104
|
+
* export const getUser = base
|
|
105
|
+
* .input(z.object({ id: z.string() }))
|
|
106
|
+
* .handler(async ({ input, context }) => {
|
|
107
|
+
* context.log.set({ user: { id: input.id } })
|
|
108
|
+
* return await db.user.findUnique(input)
|
|
109
|
+
* })
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
declare function evlog<TContext extends Partial<EvlogOrpcContext> & Context = EvlogOrpcContext>(): (options: MiddlewareOptions<TContext, unknown, any, any>) => Promise<MiddlewareResult<Record<never, never>, unknown>>;
|
|
113
|
+
//#endregion
|
|
114
|
+
export { EvlogOrpcContext, EvlogOrpcOptions, evlog, useLogger, withEvlog };
|
|
115
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/orpc/index.ts"],"mappings":";;;;;cAQiB,SAAA,sBAAS,MAAA,wBAAA,aAAA,CAAA,CAAA;;KAKd,gBAAA,GAAmB,gBAAA;;;;;;;;;AAA/B;;;;UAoBiB,gBAAA;EACf,GAAA,EAAK,aAAA;AAAA;;;;AACN;KAMI,qBAAA;EACC,OAAA;EAAe,QAAA,EAAU,QAAA;AAAA;EACzB,OAAA;EAAgB,QAAA;AAAA;;;;AAAQ;;;;;;UAWpB,oBAAA;EACR,MAAA,GACE,OAAA,EAAS,OAAA,EACT,OAAA,WACG,OAAA,CAAQ,qBAAA;AAAA;;;;;;;;AAkDf;;;;;;;;;;;;;;;;;;AA6EA;;;;;iBA7EgB,SAAA,kBAA2B,oBAAA,CAAA,CACzC,OAAA,EAAS,QAAA,EACT,OAAA,GAAS,gBAAA,GACR,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0Ea,KAAA,kBAAuB,OAAA,CAAQ,gBAAA,IAAoB,OAAA,GAAU,gBAAA,CAAA,CAAA,IAEzE,OAAA,EAAS,iBAAA,CAAkB,QAAA,yBAC1B,OAAA,CAAQ,gBAAA,CAAiB,MAAA"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { EvlogError } from "../error.mjs";
|
|
2
|
+
import { parseError } from "../runtime/utils/parseError.mjs";
|
|
3
|
+
import { t as defineFrameworkIntegration } from "../integration-CR601uyW.mjs";
|
|
4
|
+
import { t as createLoggerStorage } from "../storage-7X37OToT.mjs";
|
|
5
|
+
import { ORPCError } from "@orpc/server";
|
|
6
|
+
//#region src/orpc/index.ts
|
|
7
|
+
const { storage, useLogger } = createLoggerStorage("oRPC handler. Wrap your handler with `withEvlog()` from evlog/orpc.");
|
|
8
|
+
const integration = defineFrameworkIntegration({
|
|
9
|
+
name: "orpc",
|
|
10
|
+
extractRequest: ({ request }) => {
|
|
11
|
+
const url = new URL(request.url);
|
|
12
|
+
return {
|
|
13
|
+
method: request.method,
|
|
14
|
+
path: url.pathname,
|
|
15
|
+
headers: request.headers,
|
|
16
|
+
requestId: request.headers.get("x-request-id") ?? void 0
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
attachLogger: () => {},
|
|
20
|
+
storage
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Wrap an oRPC handler so each matched request emits a single wide event.
|
|
24
|
+
* Works with any handler that exposes `.handle(request, options)` from
|
|
25
|
+
* `@orpc/server/fetch` (RPCHandler, OpenAPIHandler, custom handlers).
|
|
26
|
+
*
|
|
27
|
+
* The returned proxy preserves the original handler's identity (instance
|
|
28
|
+
* methods, plugins, etc.) and only intercepts `handle`. Inside procedures,
|
|
29
|
+
* the request logger is exposed as `context.log` — pair this with
|
|
30
|
+
* `os.use(evlog())` to also accumulate `operation` (`path.join('.')`) on the
|
|
31
|
+
* wide event.
|
|
32
|
+
*
|
|
33
|
+
* Routes that are filtered out by `include`/`exclude` are passed straight to
|
|
34
|
+
* the underlying handler with no instrumentation.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { RPCHandler } from '@orpc/server/fetch'
|
|
39
|
+
* import { withEvlog } from 'evlog/orpc'
|
|
40
|
+
* import { router } from './router'
|
|
41
|
+
*
|
|
42
|
+
* const handler = withEvlog(new RPCHandler(router), {
|
|
43
|
+
* include: ['/rpc/**'],
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* export default async function fetch(request: Request) {
|
|
47
|
+
* const { matched, response } = await handler.handle(request, { prefix: '/rpc' })
|
|
48
|
+
* return matched ? response : new Response('Not Found', { status: 404 })
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
function withEvlog(handler, options = {}) {
|
|
53
|
+
const handle = async (request, callOptions) => {
|
|
54
|
+
const { skipped, finish, finishResponse, runWith, logger } = integration.start({ request }, options);
|
|
55
|
+
const initialContext = callOptions?.context ?? {};
|
|
56
|
+
const finalOptions = {
|
|
57
|
+
...callOptions,
|
|
58
|
+
context: {
|
|
59
|
+
...initialContext,
|
|
60
|
+
log: logger
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
if (skipped) return handler.handle(request, finalOptions);
|
|
64
|
+
try {
|
|
65
|
+
const result = await runWith(() => handler.handle(request, finalOptions));
|
|
66
|
+
if (result.matched) result.response = await finishResponse(result.response, { status: result.response.status });
|
|
67
|
+
else await finish({ status: 404 });
|
|
68
|
+
return result;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
await finish({ error });
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return new Proxy(handler, { get(target, prop, receiver) {
|
|
75
|
+
if (prop === "handle") return handle;
|
|
76
|
+
return Reflect.get(target, prop, receiver);
|
|
77
|
+
} });
|
|
78
|
+
}
|
|
79
|
+
function isEvlogError(error) {
|
|
80
|
+
return error instanceof EvlogError || error instanceof Error && error.name === "EvlogError";
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Procedure-level middleware. Three responsibilities:
|
|
84
|
+
*
|
|
85
|
+
* 1. Adds `operation` (the procedure path joined by `.`) to the wide event,
|
|
86
|
+
* so consumers can group events by procedure without parsing URLs.
|
|
87
|
+
* 2. Captures errors thrown by the procedure on the wide event so the level
|
|
88
|
+
* is promoted to `error`.
|
|
89
|
+
* 3. Converts {@link EvlogError} (from `createError()` / `defineErrorCatalog`)
|
|
90
|
+
* into a structurally-equivalent {@link ORPCError} before re-throwing, so
|
|
91
|
+
* the wire response carries the catalog `code`, status, message, and the
|
|
92
|
+
* `why` / `fix` / `link` guidance under `data` — instead of being wrapped
|
|
93
|
+
* as `INTERNAL_SERVER_ERROR` by oRPC's default handler. The catalog and
|
|
94
|
+
* `createError()` stay the canonical evlog way to author errors;
|
|
95
|
+
* `evlog/orpc` is the bridge.
|
|
96
|
+
*
|
|
97
|
+
* Requires `withEvlog()` to be wrapped around the handler — the request
|
|
98
|
+
* logger flows in via `context.log`. Declare {@link EvlogOrpcContext} on
|
|
99
|
+
* your oRPC base for typed access.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { os } from '@orpc/server'
|
|
104
|
+
* import { evlog, type EvlogOrpcContext } from 'evlog/orpc'
|
|
105
|
+
*
|
|
106
|
+
* const base = os.$context<EvlogOrpcContext>().use(evlog())
|
|
107
|
+
*
|
|
108
|
+
* export const getUser = base
|
|
109
|
+
* .input(z.object({ id: z.string() }))
|
|
110
|
+
* .handler(async ({ input, context }) => {
|
|
111
|
+
* context.log.set({ user: { id: input.id } })
|
|
112
|
+
* return await db.user.findUnique(input)
|
|
113
|
+
* })
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
function evlog() {
|
|
117
|
+
return async function evlogMiddleware(options) {
|
|
118
|
+
const { context: { log }, path, next } = options;
|
|
119
|
+
if (log && path.length > 0) log.set({ operation: path.join(".") });
|
|
120
|
+
try {
|
|
121
|
+
return await next();
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (log) log.error(error);
|
|
124
|
+
if (isEvlogError(error)) throw toOrpcError(error);
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function toOrpcError(error) {
|
|
130
|
+
const parsed = parseError(error);
|
|
131
|
+
const data = {};
|
|
132
|
+
if (parsed.why !== void 0) data.why = parsed.why;
|
|
133
|
+
if (parsed.fix !== void 0) data.fix = parsed.fix;
|
|
134
|
+
if (parsed.link !== void 0) data.link = parsed.link;
|
|
135
|
+
return new ORPCError(parsed.code ?? "EVLOG_ERROR", {
|
|
136
|
+
status: parsed.status,
|
|
137
|
+
message: parsed.message,
|
|
138
|
+
data,
|
|
139
|
+
cause: error
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
export { evlog, useLogger, withEvlog };
|
|
144
|
+
|
|
145
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/orpc/index.ts"],"sourcesContent":["import { ORPCError, type Context, type MiddlewareOptions, type MiddlewareResult } from '@orpc/server'\nimport type { RequestLogger } from '../types'\nimport { EvlogError } from '../error'\nimport { parseError } from '../runtime/utils/parseError'\nimport { defineFrameworkIntegration } from '../shared/integration'\nimport type { BaseEvlogOptions } from '../shared/middleware'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'oRPC handler. Wrap your handler with `withEvlog()` from evlog/orpc.',\n)\n\n/** Options accepted by {@link withEvlog} for oRPC request instrumentation. */\nexport type EvlogOrpcOptions = BaseEvlogOptions\n\n/**\n * Access the current request-scoped logger outside oRPC context callbacks.\n * Requires {@link withEvlog} on the handler.\n */\nexport { useLogger }\n\n/**\n * Inject this type into your oRPC initial context to access `context.log`\n * inside procedures.\n *\n * @example\n * ```ts\n * import { os } from '@orpc/server'\n * import { evlog, type EvlogOrpcContext } from 'evlog/orpc'\n *\n * const base = os.$context<EvlogOrpcContext>().use(evlog())\n * ```\n */\nexport interface EvlogOrpcContext {\n log: RequestLogger\n}\n\n/**\n * Result shape of `handler.handle()` for oRPC's fetch adapter\n * ({@link https://orpc.dev/docs/adapters/http RPCHandler / OpenAPIHandler}).\n */\ntype OrpcFetchHandleResult =\n | { matched: true, response: Response }\n | { matched: false, response: undefined }\n\n/**\n * Minimal subset of oRPC's `FetchHandler` that we need to wrap. Anything\n * compatible (RPCHandler, OpenAPIHandler, custom handler) plugs in.\n *\n * `options` is intentionally typed loosely so this matches both the\n * `(req, opts)` and `(req, opts?)` overloads that oRPC produces depending on\n * whether the router declares a non-empty initial context. The wrapper just\n * splats the original options through and injects `log` into `context`.\n */\ninterface OrpcFetchHandlerLike {\n handle: (\n request: Request,\n options?: any,\n ) => Promise<OrpcFetchHandleResult>\n}\n\nconst integration = defineFrameworkIntegration<{ request: Request }>({\n name: 'orpc',\n extractRequest: ({ request }) => {\n const url = new URL(request.url)\n return {\n method: request.method,\n path: url.pathname,\n headers: request.headers,\n requestId: request.headers.get('x-request-id') ?? undefined,\n }\n },\n attachLogger: () => {\n /* logger is injected into the oRPC context inside withEvlog() */\n },\n storage,\n})\n\n/**\n * Wrap an oRPC handler so each matched request emits a single wide event.\n * Works with any handler that exposes `.handle(request, options)` from\n * `@orpc/server/fetch` (RPCHandler, OpenAPIHandler, custom handlers).\n *\n * The returned proxy preserves the original handler's identity (instance\n * methods, plugins, etc.) and only intercepts `handle`. Inside procedures,\n * the request logger is exposed as `context.log` — pair this with\n * `os.use(evlog())` to also accumulate `operation` (`path.join('.')`) on the\n * wide event.\n *\n * Routes that are filtered out by `include`/`exclude` are passed straight to\n * the underlying handler with no instrumentation.\n *\n * @example\n * ```ts\n * import { RPCHandler } from '@orpc/server/fetch'\n * import { withEvlog } from 'evlog/orpc'\n * import { router } from './router'\n *\n * const handler = withEvlog(new RPCHandler(router), {\n * include: ['/rpc/**'],\n * })\n *\n * export default async function fetch(request: Request) {\n * const { matched, response } = await handler.handle(request, { prefix: '/rpc' })\n * return matched ? response : new Response('Not Found', { status: 404 })\n * }\n * ```\n */\nexport function withEvlog<THandler extends OrpcFetchHandlerLike>(\n handler: THandler,\n options: EvlogOrpcOptions = {},\n): THandler {\n const handle: THandler['handle'] = async (request, callOptions) => {\n const { skipped, finish, finishResponse, runWith, logger } = integration.start({ request }, options)\n\n const initialContext = (callOptions as { context?: Record<string, unknown> } | undefined)?.context ?? {}\n const finalOptions = {\n ...callOptions,\n context: { ...initialContext, log: logger },\n } as Parameters<THandler['handle']>[1]\n\n if (skipped) {\n return handler.handle(request, finalOptions)\n }\n\n try {\n const result = await runWith(() => handler.handle(request, finalOptions))\n if (result.matched) {\n result.response = await finishResponse(result.response, { status: result.response.status })\n } else {\n await finish({ status: 404 })\n }\n return result\n } catch (error) {\n await finish({ error: error as Error })\n throw error\n }\n }\n\n return new Proxy(handler, {\n get(target, prop, receiver) {\n if (prop === 'handle') return handle\n return Reflect.get(target, prop, receiver)\n },\n })\n}\n\nfunction isEvlogError(error: unknown): error is EvlogError {\n return error instanceof EvlogError || (error instanceof Error && error.name === 'EvlogError')\n}\n\n/**\n * Procedure-level middleware. Three responsibilities:\n *\n * 1. Adds `operation` (the procedure path joined by `.`) to the wide event,\n * so consumers can group events by procedure without parsing URLs.\n * 2. Captures errors thrown by the procedure on the wide event so the level\n * is promoted to `error`.\n * 3. Converts {@link EvlogError} (from `createError()` / `defineErrorCatalog`)\n * into a structurally-equivalent {@link ORPCError} before re-throwing, so\n * the wire response carries the catalog `code`, status, message, and the\n * `why` / `fix` / `link` guidance under `data` — instead of being wrapped\n * as `INTERNAL_SERVER_ERROR` by oRPC's default handler. The catalog and\n * `createError()` stay the canonical evlog way to author errors;\n * `evlog/orpc` is the bridge.\n *\n * Requires `withEvlog()` to be wrapped around the handler — the request\n * logger flows in via `context.log`. Declare {@link EvlogOrpcContext} on\n * your oRPC base for typed access.\n *\n * @example\n * ```ts\n * import { os } from '@orpc/server'\n * import { evlog, type EvlogOrpcContext } from 'evlog/orpc'\n *\n * const base = os.$context<EvlogOrpcContext>().use(evlog())\n *\n * export const getUser = base\n * .input(z.object({ id: z.string() }))\n * .handler(async ({ input, context }) => {\n * context.log.set({ user: { id: input.id } })\n * return await db.user.findUnique(input)\n * })\n * ```\n */\nexport function evlog<TContext extends Partial<EvlogOrpcContext> & Context = EvlogOrpcContext>() {\n return async function evlogMiddleware(\n options: MiddlewareOptions<TContext, unknown, any, any>,\n ): Promise<MiddlewareResult<Record<never, never>, unknown>> {\n const { context: { log }, path, next } = options\n if (log && path.length > 0) {\n log.set({ operation: path.join('.') })\n }\n try {\n return await next()\n } catch (error) {\n if (log) log.error(error as Error)\n if (isEvlogError(error)) {\n throw toOrpcError(error)\n }\n throw error\n }\n }\n}\n\nfunction toOrpcError(error: EvlogError): ORPCError<string, Record<string, unknown>> {\n const parsed = parseError(error)\n const data: Record<string, unknown> = {}\n if (parsed.why !== undefined) data.why = parsed.why\n if (parsed.fix !== undefined) data.fix = parsed.fix\n if (parsed.link !== undefined) data.link = parsed.link\n return new ORPCError(parsed.code ?? 'EVLOG_ERROR', {\n status: parsed.status,\n message: parsed.message,\n data,\n cause: error,\n })\n}\n"],"mappings":";;;;;;AAQA,MAAM,EAAE,SAAS,cAAc,oBAC7B,sEACD;AAmDD,MAAM,cAAc,2BAAiD;CACnE,MAAM;CACN,iBAAiB,EAAE,cAAc;EAC/B,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;AAChC,SAAO;GACL,QAAQ,QAAQ;GAChB,MAAM,IAAI;GACV,SAAS,QAAQ;GACjB,WAAW,QAAQ,QAAQ,IAAI,eAAe,IAAI,KAAA;GACnD;;CAEH,oBAAoB;CAGpB;CACD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCF,SAAgB,UACd,SACA,UAA4B,EAAE,EACpB;CACV,MAAM,SAA6B,OAAO,SAAS,gBAAgB;EACjE,MAAM,EAAE,SAAS,QAAQ,gBAAgB,SAAS,WAAW,YAAY,MAAM,EAAE,SAAS,EAAE,QAAQ;EAEpG,MAAM,iBAAkB,aAAmE,WAAW,EAAE;EACxG,MAAM,eAAe;GACnB,GAAG;GACH,SAAS;IAAE,GAAG;IAAgB,KAAK;IAAQ;GAC5C;AAED,MAAI,QACF,QAAO,QAAQ,OAAO,SAAS,aAAa;AAG9C,MAAI;GACF,MAAM,SAAS,MAAM,cAAc,QAAQ,OAAO,SAAS,aAAa,CAAC;AACzE,OAAI,OAAO,QACT,QAAO,WAAW,MAAM,eAAe,OAAO,UAAU,EAAE,QAAQ,OAAO,SAAS,QAAQ,CAAC;OAE3F,OAAM,OAAO,EAAE,QAAQ,KAAK,CAAC;AAE/B,UAAO;WACA,OAAO;AACd,SAAM,OAAO,EAAS,OAAgB,CAAC;AACvC,SAAM;;;AAIV,QAAO,IAAI,MAAM,SAAS,EACxB,IAAI,QAAQ,MAAM,UAAU;AAC1B,MAAI,SAAS,SAAU,QAAO;AAC9B,SAAO,QAAQ,IAAI,QAAQ,MAAM,SAAS;IAE7C,CAAC;;AAGJ,SAAS,aAAa,OAAqC;AACzD,QAAO,iBAAiB,cAAe,iBAAiB,SAAS,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqClF,SAAgB,QAAiF;AAC/F,QAAO,eAAe,gBACpB,SAC0D;EAC1D,MAAM,EAAE,SAAS,EAAE,OAAO,MAAM,SAAS;AACzC,MAAI,OAAO,KAAK,SAAS,EACvB,KAAI,IAAI,EAAE,WAAW,KAAK,KAAK,IAAI,EAAE,CAAC;AAExC,MAAI;AACF,UAAO,MAAM,MAAM;WACZ,OAAO;AACd,OAAI,IAAK,KAAI,MAAM,MAAe;AAClC,OAAI,aAAa,MAAM,CACrB,OAAM,YAAY,MAAM;AAE1B,SAAM;;;;AAKZ,SAAS,YAAY,OAA+D;CAClF,MAAM,SAAS,WAAW,MAAM;CAChC,MAAM,OAAgC,EAAE;AACxC,KAAI,OAAO,QAAQ,KAAA,EAAW,MAAK,MAAM,OAAO;AAChD,KAAI,OAAO,QAAQ,KAAA,EAAW,MAAK,MAAM,OAAO;AAChD,KAAI,OAAO,SAAS,KAAA,EAAW,MAAK,OAAO,OAAO;AAClD,QAAO,IAAI,UAAU,OAAO,QAAQ,eAAe;EACjD,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB;EACA,OAAO;EACR,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-CUhII9DA.mjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Q as ParsedError } from "./audit-BUAajsPU.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/utils/parseError.d.ts
|
|
4
4
|
declare function parseError(error: unknown): ParsedError;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { parseError as t };
|
|
7
|
-
//# sourceMappingURL=parseError-
|
|
7
|
+
//# sourceMappingURL=parseError-Cagr-Ctc.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseError-Cagr-Ctc.d.mts","names":[],"sources":["../src/runtime/utils/parseError.ts"],"mappings":";;;iBAcgB,UAAA,CAAW,KAAA,YAAiB,WAAA"}
|