evlog 2.19.1 → 2.20.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 +30 -1
- package/dist/adapters/axiom.d.mts +1 -1
- package/dist/adapters/axiom.mjs +2 -2
- 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 +1 -1
- package/dist/adapters/hyperdx.d.mts +1 -1
- package/dist/adapters/hyperdx.mjs +1 -1
- package/dist/adapters/memory.d.mts +1 -1
- package/dist/adapters/memory.mjs +1 -1
- package/dist/adapters/otlp.d.mts +1 -1
- package/dist/adapters/otlp.mjs +2 -2
- 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 +2 -2
- package/dist/ai/index.d.mts +27 -10
- package/dist/ai/index.d.mts.map +1 -1
- package/dist/ai/index.mjs +80 -15
- package/dist/ai/index.mjs.map +1 -1
- package/dist/asyncStorageScope-DnF7Xk8l.mjs +81 -0
- package/dist/asyncStorageScope-DnF7Xk8l.mjs.map +1 -0
- package/dist/{audit-BQt8yAHo.mjs → audit-BXCYMjcC.mjs} +31 -93
- package/dist/audit-BXCYMjcC.mjs.map +1 -0
- package/dist/{audit-D7v6JHj0.d.mts → audit-BZrUvjfW.d.mts} +71 -53
- package/dist/audit-BZrUvjfW.d.mts.map +1 -0
- package/dist/audit-action.d.mts +2 -0
- package/dist/audit-action.mjs +74 -0
- package/dist/audit-action.mjs.map +1 -0
- package/dist/audit.d.mts +2 -0
- package/dist/audit.mjs +3 -0
- package/dist/better-auth/index.d.mts +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/{index-EvnrXvQM.d.mts → catalog-1cQnNxR2.d.mts} +4 -3
- package/dist/catalog-1cQnNxR2.d.mts.map +1 -0
- package/dist/catalog.d.mts +2 -0
- package/dist/catalog.mjs +205 -0
- package/dist/catalog.mjs.map +1 -0
- package/dist/{define-DTQpu4f6.d.mts → define-Ct2QyrE9.d.mts} +3 -3
- package/dist/{define-DTQpu4f6.d.mts.map → define-Ct2QyrE9.d.mts.map} +1 -1
- package/dist/{drain-fDb-eNwz.mjs → drain-Dl2ZJKRA.mjs} +3 -3
- package/dist/{drain-fDb-eNwz.mjs.map → drain-Dl2ZJKRA.mjs.map} +1 -1
- package/dist/elysia/index.d.mts +8 -7
- package/dist/elysia/index.d.mts.map +1 -1
- package/dist/elysia/index.mjs +11 -8
- package/dist/elysia/index.mjs.map +1 -1
- package/dist/{enrich-error-stack-next.node-Dgm_rCf5.mjs → enrich-error-stack-next.node-KB0Oap7R.mjs} +1 -1
- package/dist/{enrich-error-stack-next.node-Dgm_rCf5.mjs.map → enrich-error-stack-next.node-KB0Oap7R.mjs.map} +1 -1
- package/dist/{enricher-CBRmQw6e.d.mts → enricher-BOzt2FCi.d.mts} +2 -2
- package/dist/{enricher-CBRmQw6e.d.mts.map → enricher-BOzt2FCi.d.mts.map} +1 -1
- package/dist/enrichers.d.mts +2 -2
- package/dist/{error-CpghjrkY.d.mts → error-BRymuv8U.d.mts} +2 -2
- package/dist/{error-CpghjrkY.d.mts.map → error-BRymuv8U.d.mts.map} +1 -1
- package/dist/error.d.mts +1 -1
- package/dist/{errors-BLU4Tfpe.d.mts → errors-C7qA6CAi.d.mts} +2 -2
- package/dist/{errors-BLU4Tfpe.d.mts.map → errors-C7qA6CAi.d.mts.map} +1 -1
- package/dist/eve/index.d.mts +72 -0
- package/dist/eve/index.d.mts.map +1 -0
- package/dist/eve/index.mjs +593 -0
- package/dist/eve/index.mjs.map +1 -0
- package/dist/express/index.d.mts +4 -4
- 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 +4 -4
- package/dist/fastify/index.d.mts.map +1 -1
- package/dist/fastify/index.mjs +4 -2
- package/dist/fastify/index.mjs.map +1 -1
- package/dist/fork-S9gpZmF8.mjs +72 -0
- package/dist/fork-S9gpZmF8.mjs.map +1 -0
- package/dist/hono/index.d.mts +3 -3
- package/dist/hono/index.d.mts.map +1 -1
- package/dist/hono/index.mjs +3 -6
- package/dist/hono/index.mjs.map +1 -1
- package/dist/{http-ChVS9GYc.mjs → http-pKfd8UDu.mjs} +2 -2
- package/dist/{http-ChVS9GYc.mjs.map → http-pKfd8UDu.mjs.map} +1 -1
- package/dist/http.d.mts +1 -1
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +3 -203
- package/dist/{instrumentation-create-BrjQtSKD.d.mts → instrumentation-create-gSDk0leX.d.mts} +2 -2
- package/dist/{instrumentation-create-BrjQtSKD.d.mts.map → instrumentation-create-gSDk0leX.d.mts.map} +1 -1
- package/dist/{integration-DYp2uw8O.mjs → integration-CeL90DtN.mjs} +3 -2
- package/dist/{integration-DYp2uw8O.mjs.map → integration-CeL90DtN.mjs.map} +1 -1
- package/dist/{logger-mHIWxBhJ.d.mts → logger-CxWz7QJ3.d.mts} +7 -3
- package/dist/logger-CxWz7QJ3.d.mts.map +1 -0
- package/dist/logger.d.mts +2 -2
- package/dist/logger.mjs +2 -2
- package/dist/{fork-CgGlAaHa.mjs → middleware-Cdebyfdt.mjs} +3 -69
- package/dist/middleware-Cdebyfdt.mjs.map +1 -0
- package/dist/{middleware-B_k4Mrzg.d.mts → middleware-fbtEs6bq.d.mts} +3 -3
- package/dist/middleware-fbtEs6bq.d.mts.map +1 -0
- package/dist/nestjs/index.d.mts +5 -5
- package/dist/nestjs/index.d.mts.map +1 -1
- package/dist/nestjs/index.mjs +4 -3
- package/dist/nestjs/index.mjs.map +1 -1
- package/dist/next/client.d.mts +1 -1
- package/dist/next/index.d.mts +5 -5
- package/dist/next/index.d.mts.map +1 -1
- package/dist/next/index.mjs +3 -3
- package/dist/next/index.mjs.map +1 -1
- package/dist/next/instrumentation/create.d.mts +1 -1
- package/dist/next/instrumentation/create.mjs +3 -1
- package/dist/next/instrumentation/create.mjs.map +1 -1
- package/dist/next/instrumentation.d.mts +1 -1
- package/dist/next/stream.d.mts +1 -1
- package/dist/nitro/errorHandler.mjs +9 -4
- package/dist/nitro/errorHandler.mjs.map +1 -1
- package/dist/nitro/module.d.mts +2 -2
- package/dist/nitro/module.mjs +1 -1
- package/dist/nitro/plugin.mjs +2 -2
- package/dist/nitro/v3/errorHandler.d.mts +0 -10
- package/dist/nitro/v3/errorHandler.mjs +13 -3
- 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.mjs +1 -1
- package/dist/nitro/v3/plugin.mjs +2 -2
- package/dist/nitro/v3/useLogger.d.mts +2 -2
- package/dist/nitro/v3/useLogger.d.mts.map +1 -1
- package/dist/nitro/v3/useLogger.mjs.map +1 -1
- package/dist/{nitro-_Hda8Deo.d.mts → nitro-CcN7HDnr.d.mts} +2 -2
- package/dist/{nitro-_Hda8Deo.d.mts.map → nitro-CcN7HDnr.d.mts.map} +1 -1
- package/dist/{nitro-ClRZLD1g.mjs → nitro-DYFCSlho.mjs} +30 -3
- package/dist/nitro-DYFCSlho.mjs.map +1 -0
- package/dist/{nitroConfigBridge-BkVWnSV3.mjs → nitroConfigBridge-lHPsE5zG.mjs} +8 -6
- package/dist/nitroConfigBridge-lHPsE5zG.mjs.map +1 -0
- package/dist/{nodeResponse-CIEEbrNE.mjs → nodeResponse-Dsl7gZUf.mjs} +1 -1
- package/dist/{nodeResponse-CIEEbrNE.mjs.map → nodeResponse-Dsl7gZUf.mjs.map} +1 -1
- package/dist/nuxt/module.d.mts +1 -1
- package/dist/nuxt/module.mjs +2 -2
- package/dist/orpc/index.d.mts +4 -4
- package/dist/orpc/index.d.mts.map +1 -1
- package/dist/orpc/index.mjs +2 -2
- package/dist/orpc/index.mjs.map +1 -1
- package/dist/{package-CNV_CXs8.mjs → package-Drb3wqqt.mjs} +2 -2
- package/dist/package-Drb3wqqt.mjs.map +1 -0
- package/dist/{parseError-BeBXEd2V.d.mts → parseError-BmoJ7XeF.d.mts} +2 -2
- package/dist/parseError-BmoJ7XeF.d.mts.map +1 -0
- package/dist/react-router/index.d.mts +4 -4
- package/dist/react-router/index.d.mts.map +1 -1
- package/dist/react-router/index.mjs +3 -2
- package/dist/react-router/index.mjs.map +1 -1
- package/dist/register-disk-snippet-B5svlT8-.mjs +21 -0
- package/dist/register-disk-snippet-B5svlT8-.mjs.map +1 -0
- package/dist/runtime/client/log.d.mts +1 -1
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs +1 -1
- package/dist/runtime/server/useLogger.d.mts +1 -1
- package/dist/runtime/server/useLogger.mjs.map +1 -1
- package/dist/runtime/utils/parseError.d.mts +2 -2
- package/dist/{storage-7X37OToT.mjs → storage-BeFdoGTI.mjs} +1 -1
- package/dist/storage-BeFdoGTI.mjs.map +1 -0
- package/dist/stream.d.mts +1 -1
- package/dist/stream.d.mts.map +1 -1
- package/dist/stream.mjs +7 -1
- package/dist/stream.mjs.map +1 -1
- package/dist/sveltekit/index.d.mts +3 -4
- package/dist/sveltekit/index.d.mts.map +1 -1
- package/dist/sveltekit/index.mjs +6 -3
- package/dist/sveltekit/index.mjs.map +1 -1
- package/dist/toolkit.d.mts +7 -7
- package/dist/toolkit.d.mts.map +1 -1
- package/dist/toolkit.mjs +7 -6
- package/dist/types.d.mts +1 -1
- package/dist/{useLogger-Cfv8Ck8b.d.mts → useLogger-BupVLO9_.d.mts} +3 -3
- package/dist/useLogger-BupVLO9_.d.mts.map +1 -0
- package/dist/{utils-CJJG0ZYW.d.mts → utils-D_LY-J1k.d.mts} +2 -2
- package/dist/{utils-CJJG0ZYW.d.mts.map → utils-D_LY-J1k.d.mts.map} +1 -1
- package/dist/utils.d.mts +1 -1
- package/dist/vite/index.d.mts +1 -1
- package/dist/workers.d.mts +3 -3
- package/dist/workers.d.mts.map +1 -1
- package/dist/workers.mjs +1 -1
- package/dist/workers.mjs.map +1 -1
- package/package.json +25 -2
- package/dist/audit-BQt8yAHo.mjs.map +0 -1
- package/dist/audit-D7v6JHj0.d.mts.map +0 -1
- package/dist/fork-CgGlAaHa.mjs.map +0 -1
- package/dist/index-EvnrXvQM.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/logger-mHIWxBhJ.d.mts.map +0 -1
- package/dist/middleware-B_k4Mrzg.d.mts.map +0 -1
- package/dist/nitro-ClRZLD1g.mjs.map +0 -1
- package/dist/nitroConfigBridge-BkVWnSV3.mjs.map +0 -1
- package/dist/package-CNV_CXs8.mjs.map +0 -1
- package/dist/parseError-BeBXEd2V.d.mts.map +0 -1
- package/dist/storage-7X37OToT.mjs.map +0 -1
- package/dist/useLogger-Cfv8Ck8b.d.mts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeResponse-
|
|
1
|
+
{"version":3,"file":"nodeResponse-Dsl7gZUf.mjs","names":[],"sources":["../src/shared/nodeResponse.ts"],"sourcesContent":["import type { ServerResponse } from 'node:http'\nimport type { RequestLogger } from '../types'\nimport type { MiddlewareLoggerResult } from './middleware'\n\n/**\n * Bind an evlog middleware {@link MiddlewareLoggerResult.finish | `finish()`}\n * to a Node {@link ServerResponse} lifecycle.\n *\n * Listens to **both** `finish` (response fully transmitted) and `close`\n * (underlying socket closed — including client disconnects mid-response).\n * Idempotent: only the first event to fire calls `finish()`.\n *\n * When `close` fires before `finish`, the client disconnected before the\n * response could complete. In that case the wide event is marked with\n * `connectionClosed: true` so disconnects are observable in the drain.\n *\n * @remarks\n * For background work that must outlive the HTTP response (e.g. resumable\n * streams, post-response usage accounting), use\n * {@link RequestLogger.fork | `req.log.fork(label, fn)`} instead of mutating\n * the request logger after the response has closed — once `finish()` has run,\n * the request logger is sealed.\n *\n * @internal Used by the Express and NestJS integrations.\n */\nexport function bindNodeResponseLifecycle(\n res: ServerResponse,\n logger: RequestLogger,\n finish: MiddlewareLoggerResult['finish'],\n): void {\n let settled = false\n\n const onFinish = (): void => {\n if (settled) return\n settled = true\n finish({ status: res.statusCode }).catch(() => {})\n }\n\n const onClose = (): void => {\n if (settled) return\n settled = true\n logger.set({ connectionClosed: true })\n finish({ status: res.statusCode }).catch(() => {})\n }\n\n res.once('finish', onFinish)\n res.once('close', onClose)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,0BACd,KACA,QACA,QACM;CACN,IAAI,UAAU;CAEd,MAAM,iBAAuB;AAC3B,MAAI,QAAS;AACb,YAAU;AACV,SAAO,EAAE,QAAQ,IAAI,YAAY,CAAC,CAAC,YAAY,GAAG;;CAGpD,MAAM,gBAAsB;AAC1B,MAAI,QAAS;AACb,YAAU;AACV,SAAO,IAAI,EAAE,kBAAkB,MAAM,CAAC;AACtC,SAAO,EAAE,QAAQ,IAAI,YAAY,CAAC,CAAC,YAAY,GAAG;;AAGpD,KAAI,KAAK,UAAU,SAAS;AAC5B,KAAI,KAAK,SAAS,QAAQ"}
|
package/dist/nuxt/module.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as LogLevel, G as EnvironmentContext, ct as RouteConfig, gt as DevTerminalInput, lt as SamplingConfig, mt as TransportConfig, nt as RedactConfig } from "../audit-BZrUvjfW.mjs";
|
|
2
2
|
import { StreamServerOptions } from "../stream.mjs";
|
|
3
3
|
import * as _$_nuxt_schema0 from "@nuxt/schema";
|
|
4
4
|
|
package/dist/nuxt/module.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as prependNitroErrorHandler } from "../nitro-
|
|
1
|
+
import { r as prependNitroErrorHandler } from "../nitro-DYFCSlho.mjs";
|
|
2
2
|
import { n as createStripPlugin, t as createSourceLocationPlugin } from "../source-location-CHOPF2nd.mjs";
|
|
3
|
-
import { n as version, t as name } from "../package-
|
|
3
|
+
import { n as version, t as name } from "../package-Drb3wqqt.mjs";
|
|
4
4
|
import { addImports, addPlugin, addServerHandler, addServerImports, addServerPlugin, addVitePlugin, createResolver, defineNuxtModule } from "@nuxt/kit";
|
|
5
5
|
//#region src/nuxt/module.ts
|
|
6
6
|
var module_default = defineNuxtModule({
|
package/dist/orpc/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as BaseEvlogOptions } from "../middleware-
|
|
1
|
+
import { l as AuditableLogger } from "../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as BaseEvlogOptions } from "../middleware-fbtEs6bq.mjs";
|
|
3
3
|
import { Context, MiddlewareOptions, MiddlewareResult } from "@orpc/server";
|
|
4
4
|
|
|
5
5
|
//#region src/orpc/index.d.ts
|
|
6
|
-
declare const useLogger: <T extends object = Record<string, unknown>>() =>
|
|
6
|
+
declare const useLogger: <T extends object = Record<string, unknown>>() => AuditableLogger<T>;
|
|
7
7
|
/** Options accepted by {@link withEvlog} for oRPC request instrumentation. */
|
|
8
8
|
type EvlogOrpcOptions = BaseEvlogOptions;
|
|
9
9
|
/**
|
|
@@ -19,7 +19,7 @@ type EvlogOrpcOptions = BaseEvlogOptions;
|
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
interface EvlogOrpcContext {
|
|
22
|
-
log:
|
|
22
|
+
log: AuditableLogger;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Result shape of `handler.handle()` for oRPC's fetch adapter
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/orpc/index.ts"],"mappings":";;;;;cAQiB,SAAA,sBAAS,MAAA,wBAAA,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/orpc/index.ts"],"mappings":";;;;;cAQiB,SAAA,sBAAS,MAAA,wBAAA,eAAA,CAAA,CAAA;;KAKd,gBAAA,GAAmB,gBAAA;;;;;;;;;AAA/B;;;;UAoBiB,gBAAA;EACf,GAAA,EAAK,eAAA;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"}
|
package/dist/orpc/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EvlogError } from "../error.mjs";
|
|
2
2
|
import { parseError } from "../runtime/utils/parseError.mjs";
|
|
3
|
-
import { t as defineFrameworkIntegration } from "../integration-
|
|
4
|
-
import { t as createLoggerStorage } from "../storage-
|
|
3
|
+
import { t as defineFrameworkIntegration } from "../integration-CeL90DtN.mjs";
|
|
4
|
+
import { t as createLoggerStorage } from "../storage-BeFdoGTI.mjs";
|
|
5
5
|
import { ORPCError } from "@orpc/server";
|
|
6
6
|
//#region src/orpc/index.ts
|
|
7
7
|
const { storage, useLogger } = createLoggerStorage("oRPC handler. Wrap your handler with `withEvlog()` from evlog/orpc.");
|
package/dist/orpc/index.mjs.map
CHANGED
|
@@ -1 +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 {
|
|
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 { AuditableLogger } from '../audit'\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: AuditableLogger\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-Drb3wqqt.mjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tt as ParsedError } from "./audit-BZrUvjfW.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-BmoJ7XeF.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseError-BmoJ7XeF.d.mts","names":[],"sources":["../src/runtime/utils/parseError.ts"],"mappings":";;;iBAcgB,UAAA,CAAW,KAAA,YAAiB,WAAA"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as BaseEvlogOptions } from "../middleware-
|
|
1
|
+
import { l as AuditableLogger } from "../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as BaseEvlogOptions } from "../middleware-fbtEs6bq.mjs";
|
|
3
3
|
import * as _$react_router0 from "react-router";
|
|
4
4
|
|
|
5
5
|
//#region src/react-router/index.d.ts
|
|
6
|
-
declare const useLogger: <T extends object = Record<string, unknown>>() =>
|
|
6
|
+
declare const useLogger: <T extends object = Record<string, unknown>>() => AuditableLogger<T>;
|
|
7
7
|
/**
|
|
8
8
|
* Typed context key for accessing the evlog logger in loaders and actions.
|
|
9
9
|
*
|
|
@@ -18,7 +18,7 @@ declare const useLogger: <T extends object = Record<string, unknown>>() => Reque
|
|
|
18
18
|
* }
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
declare const loggerContext: _$react_router0.RouterContext<
|
|
21
|
+
declare const loggerContext: _$react_router0.RouterContext<AuditableLogger>;
|
|
22
22
|
type EvlogReactRouterOptions = BaseEvlogOptions;
|
|
23
23
|
/**
|
|
24
24
|
* Create an evlog middleware for React Router.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/react-router/index.ts"],"mappings":";;;;;cAOiB,SAAA,sBAAS,MAAA,wBAAA,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/react-router/index.ts"],"mappings":";;;;;cAOiB,SAAA,sBAAS,MAAA,wBAAA,eAAA,CAAA,CAAA;;;AAL0D;;;;;;;;;;;;cAuBvE,aAAA,EAAa,eAAA,CAAA,aAAA,CAAA,eAAA;AAAA,KAEd,uBAAA,GAA0B,gBAAA;;;;;AAAtC;;;;;AAiBA;;;;iBAAgB,KAAA,CAAM,OAAA,GAAS,uBAAA;EAE3B,OAAA;EAAA;AAAA;EAAwB,OAAA,EAAS,OAAA;EAAS,OAAA;IAAW,GAAA,CAAI,GAAA,WAAc,KAAA;EAAA;AAAA,GACvE,IAAA,QAAY,OAAA,CAAQ,QAAA,MACnB,OAAA,CAAQ,QAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as extractSafeHeaders } from "../headers-VtmnWcfn.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
2
|
+
import { t as createMiddlewareLogger } from "../middleware-Cdebyfdt.mjs";
|
|
3
|
+
import { t as attachForkToLogger } from "../fork-S9gpZmF8.mjs";
|
|
4
|
+
import { t as createLoggerStorage } from "../storage-BeFdoGTI.mjs";
|
|
4
5
|
import { createContext } from "react-router";
|
|
5
6
|
//#region src/react-router/index.ts
|
|
6
7
|
const { storage, useLogger } = createLoggerStorage("middleware context. Make sure the evlog middleware is added to your route.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/react-router/index.ts"],"sourcesContent":["import { createContext } from 'react-router'\nimport type {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/react-router/index.ts"],"sourcesContent":["import { createContext } from 'react-router'\nimport type { AuditableLogger } from '../audit'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'middleware context. Make sure the evlog middleware is added to your route.',\n)\n\n/**\n * Typed context key for accessing the evlog logger in loaders and actions.\n *\n * @example\n * ```ts\n * import { loggerContext } from 'evlog/react-router'\n *\n * export async function loader({ context }: Route.LoaderArgs) {\n * const log = context.get(loggerContext)\n * log.set({ user: { id: 'u-1' } })\n * return { ok: true }\n * }\n * ```\n */\nexport const loggerContext = createContext<AuditableLogger>()\n\nexport type EvlogReactRouterOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * Create an evlog middleware for React Router.\n *\n * @example\n * ```ts\n * // app/root.tsx\n * import { evlog } from 'evlog/react-router'\n *\n * export const middleware: Route.MiddlewareFunction[] = [\n * evlog({ drain: createAxiomDrain() }),\n * ]\n * ```\n */\nexport function evlog(options: EvlogReactRouterOptions = {}) {\n return async (\n { request, context }: { request: Request; context: { set(ctx: unknown, value: unknown): void } },\n next: () => Promise<Response>,\n ): Promise<Response> => {\n const url = new URL(request.url)\n const middlewareOpts = {\n method: request.method,\n path: url.pathname,\n requestId: request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return next()\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n context.set(loggerContext, logger)\n\n try {\n const response = await storage.run(logger, () => next())\n return finishResponse(response, { status: response.status })\n } catch (error) {\n await finish({ error: error as Error })\n throw error\n }\n }\n}\n"],"mappings":";;;;;;AAOA,MAAM,EAAE,SAAS,cAAc,oBAC7B,6EACD;;;;;;;;;;;;;;;AAgBD,MAAa,gBAAgB,eAAgC;;;;;;;;;;;;;;AAmB7D,SAAgB,MAAM,UAAmC,EAAE,EAAE;AAC3D,QAAO,OACL,EAAE,SAAS,WACX,SACsB;EACtB,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;EAChC,MAAM,iBAAiB;GACrB,QAAQ,QAAQ;GAChB,MAAM,IAAI;GACV,WAAW,QAAQ,QAAQ,IAAI,eAAe,IAAI,OAAO,YAAY;GACrE,SAAS,mBAAmB,QAAQ,QAAQ;GAC5C,GAAG;GACJ;EACD,MAAM,EAAE,QAAQ,QAAQ,gBAAgB,YAAY,uBAAuB,eAAe;AAE1F,MAAI,QACF,QAAO,MAAM;AAGf,qBAAmB,SAAS,QAAQ,eAAe;AACnD,UAAQ,IAAI,eAAe,OAAO;AAElC,MAAI;GACF,MAAM,WAAW,MAAM,QAAQ,IAAI,cAAc,MAAM,CAAC;AACxD,UAAO,eAAe,UAAU,EAAE,QAAQ,SAAS,QAAQ,CAAC;WACrD,OAAO;AACd,SAAM,OAAO,EAAS,OAAgB,CAAC;AACvC,SAAM"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { o as registerPrettyErrorSnippetReader } from "./pretty-error-THg0U0w9.mjs";
|
|
2
|
+
//#region src/shared/register-disk-snippet.ts
|
|
3
|
+
/**
|
|
4
|
+
* Register the disk-backed pretty-error snippet reader when Node built-ins are available.
|
|
5
|
+
*
|
|
6
|
+
* Uses a dynamic import so Edge and non-Node bundles never parse `pretty-error-snippet.node`.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
async function registerDiskPrettyErrorSnippetReader() {
|
|
11
|
+
try {
|
|
12
|
+
const { readCodeSnippetFromDisk } = await import("./pretty-error-snippet.node-itfCajBM.mjs").then((n) => n.t);
|
|
13
|
+
registerPrettyErrorSnippetReader(readCodeSnippetFromDisk);
|
|
14
|
+
} catch {
|
|
15
|
+
registerPrettyErrorSnippetReader(null);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { registerDiskPrettyErrorSnippetReader as t };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=register-disk-snippet-B5svlT8-.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-disk-snippet-B5svlT8-.mjs","names":[],"sources":["../src/shared/register-disk-snippet.ts"],"sourcesContent":["import { registerPrettyErrorSnippetReader } from './pretty-error'\n\n/**\n * Register the disk-backed pretty-error snippet reader when Node built-ins are available.\n *\n * Uses a dynamic import so Edge and non-Node bundles never parse `pretty-error-snippet.node`.\n *\n * @internal\n */\nexport async function registerDiskPrettyErrorSnippetReader(): Promise<void> {\n try {\n const { readCodeSnippetFromDisk } = await import('./pretty-error-snippet.node.js')\n registerPrettyErrorSnippetReader(readCodeSnippetFromDisk)\n } catch {\n registerPrettyErrorSnippetReader(null)\n }\n}\n"],"mappings":";;;;;;;;;AASA,eAAsB,uCAAsD;AAC1E,KAAI;EACF,MAAM,EAAE,4BAA4B,MAAM,OAAO,4CAAA,MAAA,MAAA,EAAA,EAAA;AACjD,mCAAiC,wBAAwB;SACnD;AACN,mCAAiC,KAAK"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as LogLevel, Q as Log, mt as TransportConfig } from "../../audit-BZrUvjfW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/client/log.d.ts
|
|
4
4
|
declare function setIdentity(identity: Record<string, unknown>): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { filterSafeHeaders } from "../../../../utils.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { b as getGlobalPluginRunner, v as getEnvironment } from "../../../../audit-BXCYMjcC.mjs";
|
|
3
3
|
import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readRawBody, setResponseStatus } from "h3";
|
|
4
4
|
import { useNitroApp } from "nitropack/runtime";
|
|
5
5
|
//#region src/runtime/server/routes/_evlog/ingest.post.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as useLogger } from "../../useLogger-
|
|
1
|
+
import { t as useLogger } from "../../useLogger-BupVLO9_.mjs";
|
|
2
2
|
export { useLogger };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLogger.mjs","names":[],"sources":["../../../src/runtime/server/useLogger.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"useLogger.mjs","names":[],"sources":["../../../src/runtime/server/useLogger.ts"],"sourcesContent":["import type { AuditableLogger } from '../../audit'\nimport type { ServerEvent } from '../../types'\n\n/**\n * Returns the request logger attached to the given server event.\n *\n * @param event - The current server event containing the context with the logger.\n * @param service - Optional service name to override the default service.\n * @returns The request-scoped logger.\n * @throws Error if the logger is not initialized on the event context.\n *\n * @example\n * export default defineEventHandler((event) => {\n * const log = useLogger(event)\n * log.set({ foo: 'bar' })\n * // ...\n * })\n *\n * @example\n * // Override service name for specific routes\n * export default defineEventHandler((event) => {\n * const log = useLogger(event, 'payment-service')\n * log.set({ foo: 'bar' })\n * // ...\n * })\n *\n * @example\n * // Typed fields — must use explicit import for type checking to work\n * import { useLogger } from 'evlog'\n *\n * interface MyFields { user: { id: string; plan: string } }\n * const log = useLogger<MyFields>(event)\n * log.set({ user: { id: '123', plan: 'pro' } }) // OK\n * log.set({ foo: 'bar' }) // TS error\n */\nexport function useLogger<T extends object = Record<string, unknown>>(event: ServerEvent, service?: string): AuditableLogger<T> {\n const log = event.context.log as AuditableLogger<T> | undefined\n\n if (!log) {\n throw new Error(\n '[evlog] Logger not initialized. Make sure the evlog Nitro plugin is registered. '\n + 'If using Nuxt, add \"evlog\" to your modules.',\n )\n }\n\n if (service) {\n log.set({ service })\n }\n\n return log\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,UAAsD,OAAoB,SAAsC;CAC9H,MAAM,MAAM,MAAM,QAAQ;AAE1B,KAAI,CAAC,IACH,OAAM,IAAI,MACR,gIAED;AAGH,KAAI,QACF,KAAI,IAAI,EAAE,SAAS,CAAC;AAGtB,QAAO"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as parseError } from "../../parseError-
|
|
1
|
+
import { tt as ParsedError } from "../../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as parseError } from "../../parseError-BmoJ7XeF.mjs";
|
|
3
3
|
export { ParsedError, parseError };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-BeFdoGTI.mjs","names":[],"sources":["../src/shared/storage.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { AuditableLogger } from '../audit'\n\n/**\n * Create a request-scoped `AsyncLocalStorage` and matching `useLogger`\n * accessor. Every framework that exposes `useLogger()` (Express, Fastify,\n * NestJS, SvelteKit) calls this once at module level.\n *\n * @param contextHint - Appended to the error message when `useLogger()` is\n * called outside of a request, e.g. `\"middleware context. Make sure\n * app.use(evlog()) is registered before your routes.\"`.\n */\nexport function createLoggerStorage(contextHint: string) {\n const storage = new AsyncLocalStorage<AuditableLogger>()\n\n function useLogger<T extends object = Record<string, unknown>>(): AuditableLogger<T> {\n const logger = storage.getStore()\n if (!logger) {\n throw new Error(\n `[evlog] useLogger() was called outside of an evlog ${contextHint}`,\n )\n }\n /** @internal ALS store is untyped; cast satisfies the caller's generic `T`. */\n return logger as AuditableLogger<T>\n }\n\n return { storage, useLogger }\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,oBAAoB,aAAqB;CACvD,MAAM,UAAU,IAAI,mBAAoC;CAExD,SAAS,YAA4E;EACnF,MAAM,SAAS,QAAQ,UAAU;AACjC,MAAI,CAAC,OACH,OAAM,IAAI,MACR,sDAAsD,cACvD;;AAGH,SAAO;;AAGT,QAAO;EAAE;EAAS;EAAW"}
|
package/dist/stream.d.mts
CHANGED
package/dist/stream.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.mts","names":[],"sources":["../src/stream.ts"],"mappings":";;;;UA0BiB,kBAAA;EA+CiB;;;;;;EAxChC,MAAA;EA2BA;;;;EAtBA,MAAA,IAAU,KAAA,EAAO,SAAA;EA8BH;;;;;;EAvBd,kBAAA;AAAA;;UAIe,WAAA;EAgDgB;;;;EA3C/B,KAAA,GAAQ,GAAA,EAAK,YAAA,GAAe,YAAA,OAAmB,OAAA;EA2CoB;;;AAsJrE;;EA3LE,SAAA,GAAY,QAAA,GAAW,KAAA,EAAO,SAAA;EA2L2C;;;;;;AAS3E;EA5LE,MAAA,QAAc,qBAAA,CAAsB,SAAA;;;;AAkMtC;EA7LE,MAAA,iBAAuB,SAAA;;WAEd,eAAA;EAkMT;EAAA,SAhMS,YAAA;EA8MT;;;;EAzMA,KAAA;AAAA;;AAoOF;;;iBArNgB,iBAAA,CAAkB,OAAA,GAAS,kBAAA,GAA0B,WAAA;;;;;;;;;;;;;;;;iBAsJrD,gBAAA,CAAiB,OAAA,GAAU,kBAAA,GAAqB,WAAA;;;;AA6HhE;iBApHgB,gBAAA,CAAiB,MAAA,EAAQ,WAAA;;UAMxB,mBAAA;EA8GmE;;;;;;EAvGlF,IAAA;EAuGkF;;;
|
|
1
|
+
{"version":3,"file":"stream.d.mts","names":[],"sources":["../src/stream.ts"],"mappings":";;;;UA0BiB,kBAAA;EA+CiB;;;;;;EAxChC,MAAA;EA2BA;;;;EAtBA,MAAA,IAAU,KAAA,EAAO,SAAA;EA8BH;;;;;;EAvBd,kBAAA;AAAA;;UAIe,WAAA;EAgDgB;;;;EA3C/B,KAAA,GAAQ,GAAA,EAAK,YAAA,GAAe,YAAA,OAAmB,OAAA;EA2CoB;;;AAsJrE;;EA3LE,SAAA,GAAY,QAAA,GAAW,KAAA,EAAO,SAAA;EA2L2C;;;;;;AAS3E;EA5LE,MAAA,QAAc,qBAAA,CAAsB,SAAA;;;;AAkMtC;EA7LE,MAAA,iBAAuB,SAAA;;WAEd,eAAA;EAkMT;EAAA,SAhMS,YAAA;EA8MT;;;;EAzMA,KAAA;AAAA;;AAoOF;;;iBArNgB,iBAAA,CAAkB,OAAA,GAAS,kBAAA,GAA0B,WAAA;;;;;;;;;;;;;;;;iBAsJrD,gBAAA,CAAiB,OAAA,GAAU,kBAAA,GAAqB,WAAA;;;;AA6HhE;iBApHgB,gBAAA,CAAiB,MAAA,EAAQ,WAAA;;UAMxB,mBAAA;EA8GmE;;;;;;EAvGlF,IAAA;EAuGkF;;;AAmNpF;;;EAnTE,IAAA;EAmTuC;;;;;;EA5SvC,KAAA;;;;;;EAMA,WAAA;;;;;;EAMA,MAAA;;;;;EAKA,MAAA;;;;;;EAMA,UAAA;AAAA;;UAIe,YAAA;;WAEN,GAAA;;WAEA,IAAA;;;;;;;;WAQA,KAAA,GAAQ,GAAA,EAAK,YAAA,GAAe,YAAA,OAAmB,OAAA;;WAE/C,MAAA,EAAQ,WAAA;;EAEjB,KAAA,QAAa,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8CO,iBAAA,CAAkB,OAAA,GAAS,mBAAA,GAA2B,OAAA,CAAQ,YAAA;;iBAmNpE,yBAAA,CAAA"}
|
package/dist/stream.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as EVLOG_VERSION } from "./http-
|
|
1
|
+
import { n as EVLOG_VERSION } from "./http-pKfd8UDu.mjs";
|
|
2
2
|
//#region src/stream.ts
|
|
3
3
|
const DEFAULT_BUFFER = 500;
|
|
4
4
|
const DEFAULT_QUEUE = 1e3;
|
|
@@ -269,6 +269,12 @@ async function startStreamServer(options = {}) {
|
|
|
269
269
|
}));
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
|
+
if (url.pathname !== "/" && url.pathname !== "") {
|
|
273
|
+
writeCors(res);
|
|
274
|
+
res.writeHead(404);
|
|
275
|
+
res.end("not found");
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
272
278
|
writeCors(res);
|
|
273
279
|
res.writeHead(200, {
|
|
274
280
|
"Content-Type": "text/event-stream; charset=utf-8",
|
package/dist/stream.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.mjs","names":[],"sources":["../src/stream.ts"],"sourcesContent":["/**\n * In-process event stream — the foundation for any local consumer (devtools,\n * dashboards, CLIs, SSE/WebSocket bridges) to observe events flowing through\n * the drain pipeline without re-implementing one.\n *\n * @example\n * ```ts\n * import { createStreamDrain } from 'evlog/stream'\n *\n * const stream = createStreamDrain({ buffer: 200 })\n * nitroApp.hooks.hook('evlog:drain', stream.drain)\n *\n * stream.subscribe((event) => {\n * if (event.level === 'error') notifyOps(event)\n * })\n *\n * for await (const event of stream.events()) {\n * console.log(event.timestamp, event.action ?? event.message)\n * }\n * ```\n */\n\nimport type { DrainContext, WideEvent } from './types'\nimport { EVLOG_VERSION } from './shared/http'\n\n/** Configuration accepted by {@link createStreamDrain}. */\nexport interface StreamDrainOptions {\n /**\n * Number of recent events kept in the ring buffer and replayed to new\n * subscribers via {@link StreamDrain.recent}. Set to `0` to disable\n * replay.\n * @default 500\n */\n buffer?: number\n /**\n * Optional predicate run on each drained event — return `false` to skip\n * the event entirely (it is neither buffered nor delivered).\n */\n filter?: (event: WideEvent) => boolean\n /**\n * Per-subscriber queue size for the {@link StreamDrain.events} async\n * iterator. When the consumer falls behind by more than this many events,\n * the oldest queued events are dropped — the drain is never blocked.\n * @default 1000\n */\n perSubscriberQueue?: number\n}\n\n/** Live drain that exposes its events to in-process subscribers. */\nexport interface StreamDrain {\n /**\n * Drain callback. Pass to `nitroApp.hooks.hook('evlog:drain', stream.drain)`\n * or to a plugin via `drainPlugin('stream', stream.drain)`.\n */\n drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /**\n * Register a synchronous listener. Errors thrown by the listener are\n * caught and logged — they never affect other subscribers or the drain.\n * @returns Unsubscribe function.\n */\n subscribe: (listener: (event: WideEvent) => void) => () => void\n /**\n * Async iterator over live events. Each call returns a fresh iterator —\n * past events from the ring buffer are NOT replayed. Combine with\n * {@link StreamDrain.recent} to seed history.\n *\n * Calling `return()` (e.g. via `break`) cleanly unsubscribes.\n */\n events: () => AsyncIterableIterator<WideEvent>\n /**\n * Snapshot of buffered events (oldest first, most recent last). Useful\n * to seed a new connection / UI panel before switching to live updates.\n */\n recent: () => readonly WideEvent[]\n /** Number of currently active subscribers (sync + async iterators). */\n readonly subscriberCount: number\n /** Number of events dropped because the buffer was disabled or wrapped. */\n readonly droppedCount: number\n /**\n * Disconnect all subscribers and end any pending async iterators. The\n * stream itself remains usable — new subscriptions still work.\n */\n close: () => void\n}\n\nconst DEFAULT_BUFFER = 500\nconst DEFAULT_QUEUE = 1000\n\ninterface AsyncSubscriber {\n push: (event: WideEvent) => void\n end: () => void\n}\n\n/**\n * Create an in-process {@link StreamDrain}. Multiple stream drains can\n * coexist in the same process — they are fully independent.\n */\nexport function createStreamDrain(options: StreamDrainOptions = {}): StreamDrain {\n const bufferSize = Math.max(0, Math.floor(options.buffer ?? DEFAULT_BUFFER))\n const queueLimit = Math.max(1, Math.floor(options.perSubscriberQueue ?? DEFAULT_QUEUE))\n const { filter } = options\n\n const buffer: WideEvent[] = []\n const syncListeners = new Set<(event: WideEvent) => void>()\n const asyncSubscribers = new Set<AsyncSubscriber>()\n let dropped = 0\n\n function publish(event: WideEvent): void {\n if (filter && !filter(event)) return\n\n if (bufferSize > 0) {\n buffer.push(event)\n while (buffer.length > bufferSize) {\n buffer.shift()\n dropped++\n }\n }\n\n for (const listener of syncListeners) {\n try {\n listener(event)\n } catch (err) {\n console.error('[evlog/stream] subscriber threw:', err)\n }\n }\n\n for (const sub of asyncSubscribers) {\n sub.push(event)\n }\n }\n\n const drain: StreamDrain['drain'] = (ctx) => {\n const contexts = Array.isArray(ctx) ? ctx : [ctx]\n for (const c of contexts) {\n if (c?.event) publish(c.event)\n }\n return Promise.resolve()\n }\n\n const subscribe: StreamDrain['subscribe'] = (listener) => {\n syncListeners.add(listener)\n return () => {\n syncListeners.delete(listener)\n }\n }\n\n function createAsyncIterator(): AsyncIterableIterator<WideEvent> {\n const queue: WideEvent[] = []\n let pendingResolve: ((result: IteratorResult<WideEvent>) => void) | null = null\n let closed = false\n\n const subscriber: AsyncSubscriber = {\n push(event) {\n if (closed) return\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: event, done: false })\n return\n }\n queue.push(event)\n while (queue.length > queueLimit) {\n queue.shift()\n dropped++\n }\n },\n end() {\n if (closed) return\n closed = true\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n },\n }\n\n asyncSubscribers.add(subscriber)\n\n const iterator: AsyncIterableIterator<WideEvent> = {\n [Symbol.asyncIterator]() {\n return iterator\n },\n next(): Promise<IteratorResult<WideEvent>> {\n if (queue.length > 0) {\n return Promise.resolve({ value: queue.shift()!, done: false })\n }\n if (closed) {\n return Promise.resolve({ value: undefined, done: true })\n }\n return new Promise((resolve) => {\n pendingResolve = resolve\n })\n },\n return(): Promise<IteratorResult<WideEvent>> {\n closed = true\n asyncSubscribers.delete(subscriber)\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n return Promise.resolve({ value: undefined, done: true })\n },\n }\n\n return iterator\n }\n\n return {\n drain,\n subscribe,\n events: createAsyncIterator,\n recent: () => buffer.slice(),\n get subscriberCount() {\n return syncListeners.size + asyncSubscribers.size\n },\n get droppedCount() {\n return dropped\n },\n close() {\n syncListeners.clear()\n for (const sub of asyncSubscribers) {\n sub.end()\n }\n asyncSubscribers.clear()\n },\n }\n}\n\nlet defaultStream: StreamDrain | null = null\n\n/**\n * Lazily create / return the process-wide default {@link StreamDrain}.\n *\n * Used by built-in framework integrations (Nuxt SSE bridge, devtools panel)\n * so they share a single buffer. Custom code can subscribe to this stream\n * to observe everything draining through evlog without registering a new\n * drain.\n *\n * @example\n * ```ts\n * import { getDefaultStream } from 'evlog/stream'\n *\n * getDefaultStream().subscribe((event) => console.log(event.action))\n * ```\n */\nexport function getDefaultStream(options?: StreamDrainOptions): StreamDrain {\n if (!defaultStream) defaultStream = createStreamDrain(options)\n return defaultStream\n}\n\n/**\n * Replace or clear the default stream. Pass `null` to reset (mostly useful\n * in tests).\n */\nexport function setDefaultStream(stream: StreamDrain | null): void {\n defaultStream?.close()\n defaultStream = stream\n}\n\n/** Configuration accepted by {@link startStreamServer}. */\nexport interface StreamServerOptions {\n /**\n * TCP port to listen on. `0` (default) lets the OS pick an ephemeral port —\n * the actual port is exposed on the returned `port` / `url` and printed in\n * the startup banner.\n * @default 0\n */\n port?: number\n /**\n * Listen address. Default `127.0.0.1` — local-only, never exposed to the\n * LAN. Override to `0.0.0.0` only if you understand the security\n * implications.\n * @default '127.0.0.1'\n */\n host?: string\n /**\n * Bearer token. When set, the server requires `Authorization: Bearer\n * <token>` on every request and 401s otherwise. When unset, only\n * connections from `127.0.0.1` (and equivalent local hosts) are\n * accepted — same-origin policy applies on non-local hosts.\n */\n token?: string\n /**\n * Heartbeat interval (ms) sent as `event: ping` to keep the connection\n * alive through proxies and detect disconnects.\n * @default 15000\n */\n heartbeatMs?: number\n /**\n * Ring buffer size kept on the underlying default stream — replayed for\n * late-joining clients via `?since=<iso>`.\n * @default 500\n */\n buffer?: number\n /**\n * Print `[evlog] Stream → http://...` at startup.\n * @default true\n */\n banner?: boolean\n /**\n * Directory where `stream.url` is written so external tools can discover\n * the server. Set to `false` to disable.\n * @default '.evlog'\n */\n urlFileDir?: string | false\n}\n\n/** Return value of {@link startStreamServer}. */\nexport interface StreamServer {\n /** Listening URL, e.g. `http://127.0.0.1:51203`. */\n readonly url: string\n /** Resolved TCP port (useful when `port: 0`). */\n readonly port: number\n /**\n * Drain function — register on `evlog:drain` (Nitro / Nuxt), pass to\n * `initLogger({ drain })` (Next / standalone), or call directly.\n *\n * Equivalent to the underlying default stream's drain — events flow\n * through and reach every connected SSE client.\n */\n readonly drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /** The underlying in-process {@link StreamDrain}. */\n readonly stream: StreamDrain\n /** Stop the server, remove the URL file, and unsubscribe all clients. */\n close: () => Promise<void>\n}\n\nconst STREAM_DEFAULTS = {\n port: 0,\n host: '127.0.0.1',\n heartbeatMs: 15_000,\n buffer: 500,\n banner: true,\n urlFileDir: '.evlog' as string | false,\n}\n\nlet activeStreamServer: StreamServer | null = null\n\nfunction isLocalHost(host: string | undefined): boolean {\n if (!host) return false\n const lower = host.toLowerCase()\n return lower.startsWith('localhost') || lower.startsWith('127.0.0.1') || lower.startsWith('[::1]')\n}\n\n/**\n * Start a local HTTP server that exposes the default in-process stream over\n * Server-Sent Events. Framework-agnostic: works in any Node / Bun process\n * (Nuxt, Next.js, Hono, Express, Fastify, raw scripts).\n *\n * The server binds to `127.0.0.1` on an ephemeral port by default — local\n * tools and browser tabs from the same machine can connect, but the LAN\n * cannot reach it.\n *\n * Idempotent: subsequent calls return the same instance until `close()` is\n * called.\n *\n * @example\n * ```ts\n * import { startStreamServer } from 'evlog/stream'\n *\n * const server = await startStreamServer()\n * console.log(server.url) // → http://127.0.0.1:51203\n *\n * // Hook into your drain pipeline (Nitro example):\n * nitroApp.hooks.hook('evlog:drain', server.drain)\n *\n * // Or for a standalone script with initLogger:\n * initLogger({ drain: server.drain })\n * ```\n */\nexport async function startStreamServer(options: StreamServerOptions = {}): Promise<StreamServer> {\n if (activeStreamServer) return activeStreamServer\n\n const opts = { ...STREAM_DEFAULTS, ...options }\n const stream = getDefaultStream({ buffer: opts.buffer })\n\n const { createServer } = await import('node:http')\n const { writeFile, unlink, mkdir } = await import('node:fs/promises')\n const { unlinkSync } = await import('node:fs')\n const { join } = await import('node:path')\n\n function envelopeFrame(type: 'event' | 'replay' | 'hello', data: unknown): string {\n return `data: ${JSON.stringify({ evlog: '1', type, data })}\\n\\n`\n }\n\n function writeCors(res: import('node:http').ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Authorization, Accept')\n }\n\n const server = createServer((req, res) => {\n if (req.method === 'OPTIONS') {\n writeCors(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'GET') {\n res.writeHead(405)\n res.end('method not allowed')\n return\n }\n\n if (opts.token) {\n if (req.headers.authorization !== `Bearer ${opts.token}`) {\n writeCors(res)\n res.writeHead(401)\n res.end('unauthorized')\n return\n }\n } else {\n const origin = typeof req.headers.origin === 'string' ? req.headers.origin : null\n if (origin) {\n let originHost: string | null = null\n try {\n originHost = new URL(origin).host\n } catch {\n originHost = null\n }\n if (!isLocalHost(originHost ?? undefined)) {\n writeCors(res)\n res.writeHead(403)\n res.end('forbidden')\n return\n }\n }\n }\n\n const url = new URL(req.url ?? '/', 'http://localhost')\n\n if (url.pathname === '/info') {\n writeCors(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n return\n }\n\n writeCors(res)\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n 'Connection': 'keep-alive',\n 'X-Accel-Buffering': 'no',\n 'X-Evlog-Version': EVLOG_VERSION,\n })\n\n res.write(envelopeFrame('hello', {\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n\n const since = url.searchParams.get('since')\n const sinceMs = since ? Date.parse(since) : Number.NaN\n if (Number.isFinite(sinceMs)) {\n for (const past of stream.recent()) {\n const ts = typeof past.timestamp === 'string' ? Date.parse(past.timestamp) : Number.NaN\n if (Number.isFinite(ts) && ts >= sinceMs) {\n res.write(envelopeFrame('replay', past))\n }\n }\n }\n\n let closed = false\n const unsubscribe = stream.subscribe((event) => {\n if (closed) return\n res.write(envelopeFrame('event', event))\n })\n\n const heartbeat = setInterval(() => {\n if (closed) return\n res.write(`event: ping\\ndata: ${JSON.stringify({ evlog: '1', type: 'ping', data: { t: Date.now() } })}\\n\\n`)\n }, opts.heartbeatMs)\n\n const cleanup = () => {\n if (closed) return\n closed = true\n clearInterval(heartbeat)\n unsubscribe()\n try {\n res.end()\n } catch {\n // noop\n }\n }\n\n req.on('close', cleanup)\n req.on('error', cleanup)\n res.on('close', cleanup)\n res.on('error', cleanup)\n })\n\n const port: number = await new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(opts.port, opts.host, () => {\n const addr = server.address()\n if (addr && typeof addr === 'object') {\n resolve(addr.port)\n } else {\n reject(new Error('[evlog/stream] failed to determine listening port'))\n }\n })\n })\n\n const url = `http://${opts.host}:${port}`\n\n let urlFile: string | undefined\n if (opts.urlFileDir !== false) {\n try {\n await mkdir(opts.urlFileDir, { recursive: true })\n urlFile = join(opts.urlFileDir, 'stream.url')\n await writeFile(urlFile, url, 'utf-8')\n } catch (err) {\n console.warn('[evlog/stream] failed to write stream.url:', err)\n }\n }\n\n if (opts.banner) {\n console.info(`\\n [evlog] Stream → ${url}\\n`)\n }\n\n const exitHandler = () => {\n if (urlFile) {\n try {\n unlinkSync(urlFile)\n } catch {\n // noop\n }\n }\n server.close()\n }\n process.once('SIGINT', exitHandler)\n process.once('SIGTERM', exitHandler)\n process.once('exit', exitHandler)\n\n const close = async (): Promise<void> => {\n process.off('SIGINT', exitHandler)\n process.off('SIGTERM', exitHandler)\n process.off('exit', exitHandler)\n if (urlFile) {\n try {\n await unlink(urlFile)\n } catch {\n // noop\n }\n }\n await new Promise<void>((resolve, reject) => {\n server.close(err => err ? reject(err) : resolve())\n })\n if (activeStreamServer === result) activeStreamServer = null\n }\n\n const result: StreamServer = {\n url,\n port,\n drain: ctx => stream.drain(ctx),\n stream,\n close,\n }\n\n activeStreamServer = result\n return result\n}\n\n/** @internal Used by tests to reset state between specs. */\nexport function resetStreamServerForTests(): void {\n activeStreamServer = null\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.mjs","names":[],"sources":["../src/stream.ts"],"sourcesContent":["/**\n * In-process event stream — the foundation for any local consumer (devtools,\n * dashboards, CLIs, SSE/WebSocket bridges) to observe events flowing through\n * the drain pipeline without re-implementing one.\n *\n * @example\n * ```ts\n * import { createStreamDrain } from 'evlog/stream'\n *\n * const stream = createStreamDrain({ buffer: 200 })\n * nitroApp.hooks.hook('evlog:drain', stream.drain)\n *\n * stream.subscribe((event) => {\n * if (event.level === 'error') notifyOps(event)\n * })\n *\n * for await (const event of stream.events()) {\n * console.log(event.timestamp, event.action ?? event.message)\n * }\n * ```\n */\n\nimport type { DrainContext, WideEvent } from './types'\nimport { EVLOG_VERSION } from './shared/http'\n\n/** Configuration accepted by {@link createStreamDrain}. */\nexport interface StreamDrainOptions {\n /**\n * Number of recent events kept in the ring buffer and replayed to new\n * subscribers via {@link StreamDrain.recent}. Set to `0` to disable\n * replay.\n * @default 500\n */\n buffer?: number\n /**\n * Optional predicate run on each drained event — return `false` to skip\n * the event entirely (it is neither buffered nor delivered).\n */\n filter?: (event: WideEvent) => boolean\n /**\n * Per-subscriber queue size for the {@link StreamDrain.events} async\n * iterator. When the consumer falls behind by more than this many events,\n * the oldest queued events are dropped — the drain is never blocked.\n * @default 1000\n */\n perSubscriberQueue?: number\n}\n\n/** Live drain that exposes its events to in-process subscribers. */\nexport interface StreamDrain {\n /**\n * Drain callback. Pass to `nitroApp.hooks.hook('evlog:drain', stream.drain)`\n * or to a plugin via `drainPlugin('stream', stream.drain)`.\n */\n drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /**\n * Register a synchronous listener. Errors thrown by the listener are\n * caught and logged — they never affect other subscribers or the drain.\n * @returns Unsubscribe function.\n */\n subscribe: (listener: (event: WideEvent) => void) => () => void\n /**\n * Async iterator over live events. Each call returns a fresh iterator —\n * past events from the ring buffer are NOT replayed. Combine with\n * {@link StreamDrain.recent} to seed history.\n *\n * Calling `return()` (e.g. via `break`) cleanly unsubscribes.\n */\n events: () => AsyncIterableIterator<WideEvent>\n /**\n * Snapshot of buffered events (oldest first, most recent last). Useful\n * to seed a new connection / UI panel before switching to live updates.\n */\n recent: () => readonly WideEvent[]\n /** Number of currently active subscribers (sync + async iterators). */\n readonly subscriberCount: number\n /** Number of events dropped because the buffer was disabled or wrapped. */\n readonly droppedCount: number\n /**\n * Disconnect all subscribers and end any pending async iterators. The\n * stream itself remains usable — new subscriptions still work.\n */\n close: () => void\n}\n\nconst DEFAULT_BUFFER = 500\nconst DEFAULT_QUEUE = 1000\n\ninterface AsyncSubscriber {\n push: (event: WideEvent) => void\n end: () => void\n}\n\n/**\n * Create an in-process {@link StreamDrain}. Multiple stream drains can\n * coexist in the same process — they are fully independent.\n */\nexport function createStreamDrain(options: StreamDrainOptions = {}): StreamDrain {\n const bufferSize = Math.max(0, Math.floor(options.buffer ?? DEFAULT_BUFFER))\n const queueLimit = Math.max(1, Math.floor(options.perSubscriberQueue ?? DEFAULT_QUEUE))\n const { filter } = options\n\n const buffer: WideEvent[] = []\n const syncListeners = new Set<(event: WideEvent) => void>()\n const asyncSubscribers = new Set<AsyncSubscriber>()\n let dropped = 0\n\n function publish(event: WideEvent): void {\n if (filter && !filter(event)) return\n\n if (bufferSize > 0) {\n buffer.push(event)\n while (buffer.length > bufferSize) {\n buffer.shift()\n dropped++\n }\n }\n\n for (const listener of syncListeners) {\n try {\n listener(event)\n } catch (err) {\n console.error('[evlog/stream] subscriber threw:', err)\n }\n }\n\n for (const sub of asyncSubscribers) {\n sub.push(event)\n }\n }\n\n const drain: StreamDrain['drain'] = (ctx) => {\n const contexts = Array.isArray(ctx) ? ctx : [ctx]\n for (const c of contexts) {\n if (c?.event) publish(c.event)\n }\n return Promise.resolve()\n }\n\n const subscribe: StreamDrain['subscribe'] = (listener) => {\n syncListeners.add(listener)\n return () => {\n syncListeners.delete(listener)\n }\n }\n\n function createAsyncIterator(): AsyncIterableIterator<WideEvent> {\n const queue: WideEvent[] = []\n let pendingResolve: ((result: IteratorResult<WideEvent>) => void) | null = null\n let closed = false\n\n const subscriber: AsyncSubscriber = {\n push(event) {\n if (closed) return\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: event, done: false })\n return\n }\n queue.push(event)\n while (queue.length > queueLimit) {\n queue.shift()\n dropped++\n }\n },\n end() {\n if (closed) return\n closed = true\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n },\n }\n\n asyncSubscribers.add(subscriber)\n\n const iterator: AsyncIterableIterator<WideEvent> = {\n [Symbol.asyncIterator]() {\n return iterator\n },\n next(): Promise<IteratorResult<WideEvent>> {\n if (queue.length > 0) {\n return Promise.resolve({ value: queue.shift()!, done: false })\n }\n if (closed) {\n return Promise.resolve({ value: undefined, done: true })\n }\n return new Promise((resolve) => {\n pendingResolve = resolve\n })\n },\n return(): Promise<IteratorResult<WideEvent>> {\n closed = true\n asyncSubscribers.delete(subscriber)\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n return Promise.resolve({ value: undefined, done: true })\n },\n }\n\n return iterator\n }\n\n return {\n drain,\n subscribe,\n events: createAsyncIterator,\n recent: () => buffer.slice(),\n get subscriberCount() {\n return syncListeners.size + asyncSubscribers.size\n },\n get droppedCount() {\n return dropped\n },\n close() {\n syncListeners.clear()\n for (const sub of asyncSubscribers) {\n sub.end()\n }\n asyncSubscribers.clear()\n },\n }\n}\n\nlet defaultStream: StreamDrain | null = null\n\n/**\n * Lazily create / return the process-wide default {@link StreamDrain}.\n *\n * Used by built-in framework integrations (Nuxt SSE bridge, devtools panel)\n * so they share a single buffer. Custom code can subscribe to this stream\n * to observe everything draining through evlog without registering a new\n * drain.\n *\n * @example\n * ```ts\n * import { getDefaultStream } from 'evlog/stream'\n *\n * getDefaultStream().subscribe((event) => console.log(event.action))\n * ```\n */\nexport function getDefaultStream(options?: StreamDrainOptions): StreamDrain {\n if (!defaultStream) defaultStream = createStreamDrain(options)\n return defaultStream\n}\n\n/**\n * Replace or clear the default stream. Pass `null` to reset (mostly useful\n * in tests).\n */\nexport function setDefaultStream(stream: StreamDrain | null): void {\n defaultStream?.close()\n defaultStream = stream\n}\n\n/** Configuration accepted by {@link startStreamServer}. */\nexport interface StreamServerOptions {\n /**\n * TCP port to listen on. `0` (default) lets the OS pick an ephemeral port —\n * the actual port is exposed on the returned `port` / `url` and printed in\n * the startup banner.\n * @default 0\n */\n port?: number\n /**\n * Listen address. Default `127.0.0.1` — local-only, never exposed to the\n * LAN. Override to `0.0.0.0` only if you understand the security\n * implications.\n * @default '127.0.0.1'\n */\n host?: string\n /**\n * Bearer token. When set, the server requires `Authorization: Bearer\n * <token>` on every request and 401s otherwise. When unset, only\n * connections from `127.0.0.1` (and equivalent local hosts) are\n * accepted — same-origin policy applies on non-local hosts.\n */\n token?: string\n /**\n * Heartbeat interval (ms) sent as `event: ping` to keep the connection\n * alive through proxies and detect disconnects.\n * @default 15000\n */\n heartbeatMs?: number\n /**\n * Ring buffer size kept on the underlying default stream — replayed for\n * late-joining clients via `?since=<iso>`.\n * @default 500\n */\n buffer?: number\n /**\n * Print `[evlog] Stream → http://...` at startup.\n * @default true\n */\n banner?: boolean\n /**\n * Directory where `stream.url` is written so external tools can discover\n * the server. Set to `false` to disable.\n * @default '.evlog'\n */\n urlFileDir?: string | false\n}\n\n/** Return value of {@link startStreamServer}. */\nexport interface StreamServer {\n /** Listening URL, e.g. `http://127.0.0.1:51203`. */\n readonly url: string\n /** Resolved TCP port (useful when `port: 0`). */\n readonly port: number\n /**\n * Drain function — register on `evlog:drain` (Nitro / Nuxt), pass to\n * `initLogger({ drain })` (Next / standalone), or call directly.\n *\n * Equivalent to the underlying default stream's drain — events flow\n * through and reach every connected SSE client.\n */\n readonly drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /** The underlying in-process {@link StreamDrain}. */\n readonly stream: StreamDrain\n /** Stop the server, remove the URL file, and unsubscribe all clients. */\n close: () => Promise<void>\n}\n\nconst STREAM_DEFAULTS = {\n port: 0,\n host: '127.0.0.1',\n heartbeatMs: 15_000,\n buffer: 500,\n banner: true,\n urlFileDir: '.evlog' as string | false,\n}\n\nlet activeStreamServer: StreamServer | null = null\n\nfunction isLocalHost(host: string | undefined): boolean {\n if (!host) return false\n const lower = host.toLowerCase()\n return lower.startsWith('localhost') || lower.startsWith('127.0.0.1') || lower.startsWith('[::1]')\n}\n\n/**\n * Start a local HTTP server that exposes the default in-process stream over\n * Server-Sent Events. Framework-agnostic: works in any Node / Bun process\n * (Nuxt, Next.js, Hono, Express, Fastify, raw scripts).\n *\n * The server binds to `127.0.0.1` on an ephemeral port by default — local\n * tools and browser tabs from the same machine can connect, but the LAN\n * cannot reach it.\n *\n * Idempotent: subsequent calls return the same instance until `close()` is\n * called.\n *\n * @example\n * ```ts\n * import { startStreamServer } from 'evlog/stream'\n *\n * const server = await startStreamServer()\n * console.log(server.url) // → http://127.0.0.1:51203\n *\n * // Hook into your drain pipeline (Nitro example):\n * nitroApp.hooks.hook('evlog:drain', server.drain)\n *\n * // Or for a standalone script with initLogger:\n * initLogger({ drain: server.drain })\n * ```\n */\nexport async function startStreamServer(options: StreamServerOptions = {}): Promise<StreamServer> {\n if (activeStreamServer) return activeStreamServer\n\n const opts = { ...STREAM_DEFAULTS, ...options }\n const stream = getDefaultStream({ buffer: opts.buffer })\n\n const { createServer } = await import('node:http')\n const { writeFile, unlink, mkdir } = await import('node:fs/promises')\n const { unlinkSync } = await import('node:fs')\n const { join } = await import('node:path')\n\n function envelopeFrame(type: 'event' | 'replay' | 'hello', data: unknown): string {\n return `data: ${JSON.stringify({ evlog: '1', type, data })}\\n\\n`\n }\n\n function writeCors(res: import('node:http').ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Authorization, Accept')\n }\n\n const server = createServer((req, res) => {\n if (req.method === 'OPTIONS') {\n writeCors(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'GET') {\n res.writeHead(405)\n res.end('method not allowed')\n return\n }\n\n if (opts.token) {\n if (req.headers.authorization !== `Bearer ${opts.token}`) {\n writeCors(res)\n res.writeHead(401)\n res.end('unauthorized')\n return\n }\n } else {\n const origin = typeof req.headers.origin === 'string' ? req.headers.origin : null\n if (origin) {\n let originHost: string | null = null\n try {\n originHost = new URL(origin).host\n } catch {\n originHost = null\n }\n if (!isLocalHost(originHost ?? undefined)) {\n writeCors(res)\n res.writeHead(403)\n res.end('forbidden')\n return\n }\n }\n }\n\n const url = new URL(req.url ?? '/', 'http://localhost')\n\n if (url.pathname === '/info') {\n writeCors(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n return\n }\n\n // Only the root path is SSE — stray GETs (e.g. health probes) must not\n // return 200 or tooling that scans stdout for loopback URLs can mis-detect\n // this server as something else (eve/next dev proxy is one real case).\n if (url.pathname !== '/' && url.pathname !== '') {\n writeCors(res)\n res.writeHead(404)\n res.end('not found')\n return\n }\n\n writeCors(res)\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n 'Connection': 'keep-alive',\n 'X-Accel-Buffering': 'no',\n 'X-Evlog-Version': EVLOG_VERSION,\n })\n\n res.write(envelopeFrame('hello', {\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n\n const since = url.searchParams.get('since')\n const sinceMs = since ? Date.parse(since) : Number.NaN\n if (Number.isFinite(sinceMs)) {\n for (const past of stream.recent()) {\n const ts = typeof past.timestamp === 'string' ? Date.parse(past.timestamp) : Number.NaN\n if (Number.isFinite(ts) && ts >= sinceMs) {\n res.write(envelopeFrame('replay', past))\n }\n }\n }\n\n let closed = false\n const unsubscribe = stream.subscribe((event) => {\n if (closed) return\n res.write(envelopeFrame('event', event))\n })\n\n const heartbeat = setInterval(() => {\n if (closed) return\n res.write(`event: ping\\ndata: ${JSON.stringify({ evlog: '1', type: 'ping', data: { t: Date.now() } })}\\n\\n`)\n }, opts.heartbeatMs)\n\n const cleanup = () => {\n if (closed) return\n closed = true\n clearInterval(heartbeat)\n unsubscribe()\n try {\n res.end()\n } catch {\n // noop\n }\n }\n\n req.on('close', cleanup)\n req.on('error', cleanup)\n res.on('close', cleanup)\n res.on('error', cleanup)\n })\n\n const port: number = await new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(opts.port, opts.host, () => {\n const addr = server.address()\n if (addr && typeof addr === 'object') {\n resolve(addr.port)\n } else {\n reject(new Error('[evlog/stream] failed to determine listening port'))\n }\n })\n })\n\n const url = `http://${opts.host}:${port}`\n\n let urlFile: string | undefined\n if (opts.urlFileDir !== false) {\n try {\n await mkdir(opts.urlFileDir, { recursive: true })\n urlFile = join(opts.urlFileDir, 'stream.url')\n await writeFile(urlFile, url, 'utf-8')\n } catch (err) {\n console.warn('[evlog/stream] failed to write stream.url:', err)\n }\n }\n\n if (opts.banner) {\n console.info(`\\n [evlog] Stream → ${url}\\n`)\n }\n\n const exitHandler = () => {\n if (urlFile) {\n try {\n unlinkSync(urlFile)\n } catch {\n // noop\n }\n }\n server.close()\n }\n process.once('SIGINT', exitHandler)\n process.once('SIGTERM', exitHandler)\n process.once('exit', exitHandler)\n\n const close = async (): Promise<void> => {\n process.off('SIGINT', exitHandler)\n process.off('SIGTERM', exitHandler)\n process.off('exit', exitHandler)\n if (urlFile) {\n try {\n await unlink(urlFile)\n } catch {\n // noop\n }\n }\n await new Promise<void>((resolve, reject) => {\n server.close(err => err ? reject(err) : resolve())\n })\n if (activeStreamServer === result) activeStreamServer = null\n }\n\n const result: StreamServer = {\n url,\n port,\n drain: ctx => stream.drain(ctx),\n stream,\n close,\n }\n\n activeStreamServer = result\n return result\n}\n\n/** @internal Used by tests to reset state between specs. */\nexport function resetStreamServerForTests(): void {\n activeStreamServer = null\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as BaseEvlogOptions } from "../middleware-
|
|
3
|
-
|
|
1
|
+
import { l as AuditableLogger } from "../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as BaseEvlogOptions } from "../middleware-fbtEs6bq.mjs";
|
|
4
3
|
//#region src/sveltekit/index.d.ts
|
|
5
|
-
declare const useLogger: <T extends object = Record<string, unknown>>() =>
|
|
4
|
+
declare const useLogger: <T extends object = Record<string, unknown>>() => AuditableLogger<T>;
|
|
6
5
|
type EvlogSvelteKitOptions = BaseEvlogOptions;
|
|
7
6
|
/**
|
|
8
7
|
* SvelteKit `Handle` function signature — avoids a hard dependency on `@sveltejs/kit`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/sveltekit/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/sveltekit/index.ts"],"mappings":";;;cASiB,SAAA,sBAAS,MAAA,wBAAA,eAAA,CAAA,CAAA;AAAA,KAMd,qBAAA,GAAwB,gBAAA;;AAbgD;;KAoB/E,eAAA,IAAmB,KAAA;EACtB,KAAA;IAAS,OAAA,EAAS,OAAA;IAAS,GAAA,EAAK,GAAA;IAAK,MAAA,EAAQ,MAAA;EAAA;EAC7C,OAAA,MAAa,IAAA,YAAgB,QAAA,GAAW,OAAA,CAAQ,QAAA;AAAA,MAC5C,OAAA,CAAQ,QAAA;;;;KAKT,0BAAA,IAA8B,KAAA;EACjC,KAAA;EACA,KAAA;IAAS,OAAA,EAAS,OAAA;IAAS,GAAA,EAAK,GAAA;IAAK,MAAA,EAAQ,MAAA;EAAA;EAC7C,MAAA;EACA,OAAA;AAAA,MACI,YAAA,QAAoB,QAAA;AAAA,KAErB,YAAA,MAAkB,CAAA,GAAI,OAAA,CAAQ,CAAA;;UAGzB,QAAA;EACR,OAAA;EAAA,CACC,GAAA;AAAA;;;;;;;;;;;;;;;;;;;;;AAjBmB;;;;;;;;;;;;iBA2GN,KAAA,CAAM,OAAA,GAAS,qBAAA,GAA6B,eAAA;;;;;;;;;;;;;AAjG1B;;;;iBA0KlB,gBAAA,CAAA,GAAoB,0BAAA;;;;;;;;;;AAxKA;;;;;AA+FpC;;;;;;;;;AAyEA;;;;;AA2DA;;;;;;;iBAAgB,gBAAA,CAAiB,OAAA,GAAS,qBAAA"}
|
package/dist/sveltekit/index.mjs
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { EvlogError } from "../error.mjs";
|
|
2
2
|
import { t as extractSafeHeaders } from "../headers-VtmnWcfn.mjs";
|
|
3
3
|
import { t as extractErrorStatus } from "../errors-DA0cyr8q.mjs";
|
|
4
|
-
import { a as serializeEvlogErrorResponse, i as resolveEvlogError } from "../nitro-
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
4
|
+
import { a as serializeEvlogErrorResponse, i as resolveEvlogError } from "../nitro-DYFCSlho.mjs";
|
|
5
|
+
import { t as createMiddlewareLogger } from "../middleware-Cdebyfdt.mjs";
|
|
6
|
+
import { t as attachForkToLogger } from "../fork-S9gpZmF8.mjs";
|
|
7
|
+
import { t as registerDiskPrettyErrorSnippetReader } from "../register-disk-snippet-B5svlT8-.mjs";
|
|
8
|
+
import { t as createLoggerStorage } from "../storage-BeFdoGTI.mjs";
|
|
7
9
|
//#region src/sveltekit/index.ts
|
|
8
10
|
const { storage, useLogger } = createLoggerStorage("handle context. Make sure evlog() handle is added to your hooks.server.ts.");
|
|
11
|
+
registerDiskPrettyErrorSnippetReader();
|
|
9
12
|
function isPlainObject(value) {
|
|
10
13
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/sveltekit/index.ts"],"sourcesContent":["import type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\nimport { resolveEvlogError, extractErrorStatus, serializeEvlogErrorResponse } from '../nitro'\nimport { EvlogError } from '../error'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'handle context. Make sure evlog() handle is added to your hooks.server.ts.',\n)\n\nexport type EvlogSvelteKitOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * SvelteKit `Handle` function signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandle = (input: {\n event: { request: Request; url: URL; locals: Record<string, any> }\n resolve: (...args: any[]) => Response | Promise<Response>\n}) => Promise<Response>\n\n/**\n * SvelteKit `HandleServerError` signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandleServerError = (input: {\n error: unknown\n event: { request: Request; url: URL; locals: Record<string, any> }\n status: number\n message: string\n}) => MaybePromise<void | AppError>\n\ntype MaybePromise<T> = T | Promise<T>\n\n/** Minimal SvelteKit `App.Error` shape */\ninterface AppError {\n message: string\n [key: string]: unknown\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isRequestLogger(value: unknown): value is RequestLogger {\n return isPlainObject(value)\n && typeof value.error === 'function'\n && typeof value.emit === 'function'\n}\n\ninterface ContextEvlogError {\n name: 'EvlogError'\n status: number\n message: string\n why?: string\n fix?: string\n link?: string\n code?: string\n}\n\nfunction isContextEvlogError(value: unknown): value is Record<string, unknown> & ContextEvlogError {\n return isPlainObject(value)\n && value.name === 'EvlogError'\n && typeof value.status === 'number'\n && typeof value.message === 'string'\n}\n\nfunction evlogErrorFromContext(errorData: Record<string, unknown>): EvlogError {\n const nested = isPlainObject(errorData.data) ? errorData.data : undefined\n const readString = (key: string): string | undefined => {\n const direct = errorData[key]\n if (typeof direct === 'string') return direct\n const fromNested = nested?.[key]\n return typeof fromNested === 'string' ? fromNested : undefined\n }\n return new EvlogError({\n message: String(errorData.message),\n status: errorData.status as number,\n code: readString('code'),\n why: readString('why'),\n fix: readString('fix'),\n link: readString('link'),\n })\n}\n\nfunction readEvlogResponseData(response: Record<string, unknown>): { why?: string, fix?: string, link?: string } {\n const { data } = response\n if (!isPlainObject(data)) return {}\n return {\n why: typeof data.why === 'string' ? data.why : undefined,\n fix: typeof data.fix === 'string' ? data.fix : undefined,\n link: typeof data.link === 'string' ? data.link : undefined,\n }\n}\n\n/**\n * Create an evlog handle hook for SvelteKit.\n *\n * Add it to your `src/hooks.server.ts` using SvelteKit's `sequence` helper\n * or as the sole handle export.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { evlog } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-sveltekit-app' } })\n *\n * export const handle = evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { evlog } from 'evlog/sveltekit'\n *\n * export const handle = sequence(evlog(), yourOtherHook)\n * ```\n */\nexport function evlog(options: EvlogSvelteKitOptions = {}): SvelteKitHandle {\n return async ({ event, resolve }) => {\n const middlewareOpts = {\n method: event.request.method,\n path: event.url.pathname,\n requestId: event.request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(event.request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return await resolve(event)\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n event.locals.log = logger\n\n return storage.run(logger, async () => {\n try {\n const response = await resolve(event)\n\n // SvelteKit catches route errors internally and returns 500.\n // If handleError already logged an EvlogError with a specific status,\n // return a structured JSON response instead of SvelteKit's generic 500.\n const ctx = logger.getContext()\n const errorData = ctx.error\n if (response.status >= 500 && isContextEvlogError(errorData)) {\n const { status } = errorData\n await finish({ status })\n const body = serializeEvlogErrorResponse(evlogErrorFromContext(errorData), event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n return finishResponse(response)\n } catch (error) {\n await finish({ error: error instanceof Error ? error : new Error(String(error)) })\n\n // Return structured JSON for EvlogError (like NextJS withEvlog / Nuxt errorHandler)\n if (error instanceof EvlogError) {\n const status = error.status ?? 500\n const body = serializeEvlogErrorResponse(error, event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n throw error\n }\n })\n }\n}\n\n/**\n * Create an evlog error handler for SvelteKit.\n *\n * Logs unhandled errors via `event.locals.log` (if available) and returns\n * structured error responses for `EvlogError` instances. For non-evlog errors,\n * returns a generic error response with sanitized messages in production.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { evlog, evlogHandleError } from 'evlog/sveltekit'\n *\n * export const handle = evlog()\n * export const handleError = evlogHandleError()\n * ```\n */\nexport function evlogHandleError(): SvelteKitHandleServerError {\n return ({ error, event, status, message }) => {\n const logger = isRequestLogger(event.locals.log) ? event.locals.log : undefined\n\n if (logger && error instanceof Error) {\n logger.error(error)\n }\n\n const evlogError = error instanceof Error ? resolveEvlogError(error) : null\n\n if (evlogError) {\n const errorStatus = extractErrorStatus(evlogError)\n const response = serializeEvlogErrorResponse(evlogError, event.url.pathname)\n return {\n message: typeof response.message === 'string' ? response.message : message,\n status: errorStatus,\n ...readEvlogResponseData(response),\n }\n }\n\n return { message, status }\n }\n}\n\n/**\n * Create both `handle` and `handleError` hooks in a single call.\n *\n * This is the recommended setup for SvelteKit — it returns both hooks\n * pre-configured and ready to export from `hooks.server.ts`.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-app' } })\n *\n * export const { handle, handleError } = createEvlogHooks({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n *\n * const evlogHooks = createEvlogHooks()\n *\n * export const handle = sequence(evlogHooks.handle, yourOtherHook)\n * export const handleError = evlogHooks.handleError\n * ```\n */\nexport function createEvlogHooks(options: EvlogSvelteKitOptions = {}) {\n return {\n handle: evlog(options),\n handleError: evlogHandleError(),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/sveltekit/index.ts"],"sourcesContent":["import type { RequestLogger } from '../types'\nimport { registerDiskPrettyErrorSnippetReader } from '../shared/register-disk-snippet'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\nimport { resolveEvlogError, extractErrorStatus, serializeEvlogErrorResponse } from '../nitro'\nimport { EvlogError } from '../error'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'handle context. Make sure evlog() handle is added to your hooks.server.ts.',\n)\n\nvoid registerDiskPrettyErrorSnippetReader()\n\nexport type EvlogSvelteKitOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * SvelteKit `Handle` function signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandle = (input: {\n event: { request: Request; url: URL; locals: Record<string, any> }\n resolve: (...args: any[]) => Response | Promise<Response>\n}) => Promise<Response>\n\n/**\n * SvelteKit `HandleServerError` signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandleServerError = (input: {\n error: unknown\n event: { request: Request; url: URL; locals: Record<string, any> }\n status: number\n message: string\n}) => MaybePromise<void | AppError>\n\ntype MaybePromise<T> = T | Promise<T>\n\n/** Minimal SvelteKit `App.Error` shape */\ninterface AppError {\n message: string\n [key: string]: unknown\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isRequestLogger(value: unknown): value is RequestLogger {\n return isPlainObject(value)\n && typeof value.error === 'function'\n && typeof value.emit === 'function'\n}\n\ninterface ContextEvlogError {\n name: 'EvlogError'\n status: number\n message: string\n why?: string\n fix?: string\n link?: string\n code?: string\n}\n\nfunction isContextEvlogError(value: unknown): value is Record<string, unknown> & ContextEvlogError {\n return isPlainObject(value)\n && value.name === 'EvlogError'\n && typeof value.status === 'number'\n && typeof value.message === 'string'\n}\n\nfunction evlogErrorFromContext(errorData: Record<string, unknown>): EvlogError {\n const nested = isPlainObject(errorData.data) ? errorData.data : undefined\n const readString = (key: string): string | undefined => {\n const direct = errorData[key]\n if (typeof direct === 'string') return direct\n const fromNested = nested?.[key]\n return typeof fromNested === 'string' ? fromNested : undefined\n }\n return new EvlogError({\n message: String(errorData.message),\n status: errorData.status as number,\n code: readString('code'),\n why: readString('why'),\n fix: readString('fix'),\n link: readString('link'),\n })\n}\n\nfunction readEvlogResponseData(response: Record<string, unknown>): { why?: string, fix?: string, link?: string } {\n const { data } = response\n if (!isPlainObject(data)) return {}\n return {\n why: typeof data.why === 'string' ? data.why : undefined,\n fix: typeof data.fix === 'string' ? data.fix : undefined,\n link: typeof data.link === 'string' ? data.link : undefined,\n }\n}\n\n/**\n * Create an evlog handle hook for SvelteKit.\n *\n * Add it to your `src/hooks.server.ts` using SvelteKit's `sequence` helper\n * or as the sole handle export.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { evlog } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-sveltekit-app' } })\n *\n * export const handle = evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { evlog } from 'evlog/sveltekit'\n *\n * export const handle = sequence(evlog(), yourOtherHook)\n * ```\n */\nexport function evlog(options: EvlogSvelteKitOptions = {}): SvelteKitHandle {\n return async ({ event, resolve }) => {\n const middlewareOpts = {\n method: event.request.method,\n path: event.url.pathname,\n requestId: event.request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(event.request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return await resolve(event)\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n event.locals.log = logger\n\n return storage.run(logger, async () => {\n try {\n const response = await resolve(event)\n\n // SvelteKit catches route errors internally and returns 500.\n // If handleError already logged an EvlogError with a specific status,\n // return a structured JSON response instead of SvelteKit's generic 500.\n const ctx = logger.getContext()\n const errorData = ctx.error\n if (response.status >= 500 && isContextEvlogError(errorData)) {\n const { status } = errorData\n await finish({ status })\n const body = serializeEvlogErrorResponse(evlogErrorFromContext(errorData), event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n return finishResponse(response)\n } catch (error) {\n await finish({ error: error instanceof Error ? error : new Error(String(error)) })\n\n // Return structured JSON for EvlogError (like NextJS withEvlog / Nuxt errorHandler)\n if (error instanceof EvlogError) {\n const status = error.status ?? 500\n const body = serializeEvlogErrorResponse(error, event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n throw error\n }\n })\n }\n}\n\n/**\n * Create an evlog error handler for SvelteKit.\n *\n * Logs unhandled errors via `event.locals.log` (if available) and returns\n * structured error responses for `EvlogError` instances. For non-evlog errors,\n * returns a generic error response with sanitized messages in production.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { evlog, evlogHandleError } from 'evlog/sveltekit'\n *\n * export const handle = evlog()\n * export const handleError = evlogHandleError()\n * ```\n */\nexport function evlogHandleError(): SvelteKitHandleServerError {\n return ({ error, event, status, message }) => {\n const logger = isRequestLogger(event.locals.log) ? event.locals.log : undefined\n\n if (logger && error instanceof Error) {\n logger.error(error)\n }\n\n const evlogError = error instanceof Error ? resolveEvlogError(error) : null\n\n if (evlogError) {\n const errorStatus = extractErrorStatus(evlogError)\n const response = serializeEvlogErrorResponse(evlogError, event.url.pathname)\n return {\n message: typeof response.message === 'string' ? response.message : message,\n status: errorStatus,\n ...readEvlogResponseData(response),\n }\n }\n\n return { message, status }\n }\n}\n\n/**\n * Create both `handle` and `handleError` hooks in a single call.\n *\n * This is the recommended setup for SvelteKit — it returns both hooks\n * pre-configured and ready to export from `hooks.server.ts`.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-app' } })\n *\n * export const { handle, handleError } = createEvlogHooks({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n *\n * const evlogHooks = createEvlogHooks()\n *\n * export const handle = sequence(evlogHooks.handle, yourOtherHook)\n * export const handleError = evlogHooks.handleError\n * ```\n */\nexport function createEvlogHooks(options: EvlogSvelteKitOptions = {}) {\n return {\n handle: evlog(options),\n handleError: evlogHandleError(),\n }\n}\n"],"mappings":"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"}
|
package/dist/toolkit.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as resolveMiddlewarePluginRunner, i as createMiddlewareLogger, n as MiddlewareLoggerOptions, o as runEnrichAndDrain, r as MiddlewareLoggerResult, t as BaseEvlogOptions } from "./middleware-
|
|
3
|
-
import { i as toMiddlewareOptions, n as defineEvlog, r as toLoggerConfig, t as EvlogConfig } from "./define-
|
|
4
|
-
import { n as EnricherOptions, r as defineEnricher, t as EnricherDefinition } from "./enricher-
|
|
5
|
-
import { n as getServiceForPath, r as shouldLog, t as extractErrorStatus } from "./errors-
|
|
1
|
+
import { $ as LogLevel, Ct as createPluginRunner, Dt as getEmptyPluginRunner, Et as enricherPlugin, St as RequestLifecycleContext, Tt as drainPlugin, U as DrainContext, W as EnrichContext, _t as ClientLogContext, bt as PluginSetupContext, ht as WideEvent, l as AuditableLogger, ot as RequestLogger, pt as TailSamplingContext, vt as EvlogPlugin, wt as definePlugin, xt as RequestFinishContext, yt as PluginRunner } from "./audit-BZrUvjfW.mjs";
|
|
2
|
+
import { a as resolveMiddlewarePluginRunner, i as createMiddlewareLogger, n as MiddlewareLoggerOptions, o as runEnrichAndDrain, r as MiddlewareLoggerResult, t as BaseEvlogOptions } from "./middleware-fbtEs6bq.mjs";
|
|
3
|
+
import { i as toMiddlewareOptions, n as defineEvlog, r as toLoggerConfig, t as EvlogConfig } from "./define-Ct2QyrE9.mjs";
|
|
4
|
+
import { n as EnricherOptions, r as defineEnricher, t as EnricherDefinition } from "./enricher-BOzt2FCi.mjs";
|
|
5
|
+
import { n as getServiceForPath, r as shouldLog, t as extractErrorStatus } from "./errors-C7qA6CAi.mjs";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
|
|
8
8
|
//#region src/shared/streamResponse.d.ts
|
|
@@ -423,8 +423,8 @@ declare const OTEL_SEVERITY_TEXT: Record<LogLevel, string>;
|
|
|
423
423
|
* app.use(evlog()) is registered before your routes."`.
|
|
424
424
|
*/
|
|
425
425
|
declare function createLoggerStorage(contextHint: string): {
|
|
426
|
-
storage: AsyncLocalStorage<
|
|
427
|
-
useLogger: <T extends object = Record<string, unknown>>() =>
|
|
426
|
+
storage: AsyncLocalStorage<AuditableLogger>;
|
|
427
|
+
useLogger: <T extends object = Record<string, unknown>>() => AuditableLogger<T>;
|
|
428
428
|
};
|
|
429
429
|
//#endregion
|
|
430
430
|
export { AttributeValueKind, BaseEvlogOptions, ClientLogContext, ConfigField, DrainOptions, EVLOG_USER_AGENT, EVLOG_VERSION, EnricherDefinition, EnricherOptions, EvlogConfig, EvlogPlugin, ExtractedRequest, ForkBackgroundLoggerOptions, ForkLifecycle, FrameworkIntegrationHelpers, FrameworkIntegrationSpec, FrameworkRequestHandle, HttpDrainOptions, HttpDrainRequest, HttpPostOptions, MiddlewareLoggerOptions, MiddlewareLoggerResult, OTEL_SEVERITY_NUMBER, OTEL_SEVERITY_TEXT, PluginRunner, PluginSetupContext, RequestFinishContext, RequestLifecycleContext, StreamCompleteMeta, TypedAttributeValue, applyDeprecatedAlias, attachForkToLogger, bindStreamingResponseLifecycle, composeDrains, composeEnrichers, composeKeep, composePlugins, createLoggerStorage, createMiddlewareLogger, createPluginRunner, defineDrain, defineEnricher, defineEvlog, defineFrameworkIntegration, defineHttpDrain, definePlugin, drainPlugin, enricherPlugin, extractErrorStatus, extractSafeHeaders, extractSafeNodeHeaders, forkBackgroundLogger, formatPublicEnvKeys, getEmptyPluginRunner, getHeader, getRuntimeConfig, getServiceForPath, httpPost, isStreamingResponse, mergeEventField, normalizeNumber, resolveAdapterConfig, resolveMiddlewarePluginRunner, runEnrichAndDrain, shouldDeferEmitForResponse, shouldLog, toLoggerConfig, toMiddlewareOptions, toOtlpAttributeValue, toTypedAttributeValue, withEvlogIdentityHeaders };
|