evlog 2.19.2 → 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-CL0q7GJU.mjs → audit-BXCYMjcC.mjs} +21 -6
- package/dist/audit-BXCYMjcC.mjs.map +1 -0
- package/dist/{audit-CBfv3rl1.d.mts → audit-BZrUvjfW.d.mts} +2 -1
- package/dist/{audit-CBfv3rl1.d.mts.map → audit-BZrUvjfW.d.mts.map} +1 -1
- package/dist/audit-action.d.mts +1 -1
- package/dist/audit.d.mts +1 -1
- package/dist/audit.mjs +1 -1
- package/dist/better-auth/index.d.mts +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/{catalog-CyemiLYG.d.mts → catalog-1cQnNxR2.d.mts} +3 -3
- package/dist/{catalog-CyemiLYG.d.mts.map → catalog-1cQnNxR2.d.mts.map} +1 -1
- package/dist/catalog.d.mts +1 -1
- package/dist/{define-BuDJpV2b.d.mts → define-Ct2QyrE9.d.mts} +3 -3
- package/dist/{define-BuDJpV2b.d.mts.map → define-Ct2QyrE9.d.mts.map} +1 -1
- package/dist/{drain-6lV-g7JB.mjs → drain-Dl2ZJKRA.mjs} +3 -3
- package/dist/{drain-6lV-g7JB.mjs.map → drain-Dl2ZJKRA.mjs.map} +1 -1
- package/dist/elysia/index.d.mts +6 -5
- 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-BecxSKUc.mjs → enrich-error-stack-next.node-KB0Oap7R.mjs} +1 -1
- package/dist/{enrich-error-stack-next.node-BecxSKUc.mjs.map → enrich-error-stack-next.node-KB0Oap7R.mjs.map} +1 -1
- package/dist/{enricher-VdBVX4oT.d.mts → enricher-BOzt2FCi.d.mts} +2 -2
- package/dist/{enricher-VdBVX4oT.d.mts.map → enricher-BOzt2FCi.d.mts.map} +1 -1
- package/dist/enrichers.d.mts +2 -2
- package/dist/{error-CPCM5a1D.d.mts → error-BRymuv8U.d.mts} +2 -2
- package/dist/{error-CPCM5a1D.d.mts.map → error-BRymuv8U.d.mts.map} +1 -1
- package/dist/error.d.mts +1 -1
- package/dist/{errors-ZdY6Ohi6.d.mts → errors-C7qA6CAi.d.mts} +2 -2
- package/dist/{errors-ZdY6Ohi6.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 +2 -2
- package/dist/express/index.mjs +3 -3
- package/dist/fastify/index.d.mts +2 -2
- package/dist/fastify/index.mjs +3 -3
- package/dist/fork-S9gpZmF8.mjs +72 -0
- package/dist/fork-S9gpZmF8.mjs.map +1 -0
- package/dist/hono/index.d.mts +2 -2
- package/dist/hono/index.mjs +1 -1
- package/dist/{http-DA3RWQrm.mjs → http-pKfd8UDu.mjs} +2 -2
- package/dist/{http-DA3RWQrm.mjs.map → http-pKfd8UDu.mjs.map} +1 -1
- package/dist/http.d.mts +1 -1
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +1 -1
- package/dist/{instrumentation-create-STGmQGQt.d.mts → instrumentation-create-gSDk0leX.d.mts} +2 -2
- package/dist/{instrumentation-create-STGmQGQt.d.mts.map → instrumentation-create-gSDk0leX.d.mts.map} +1 -1
- package/dist/{integration-2PpI-bCm.mjs → integration-CeL90DtN.mjs} +3 -2
- package/dist/{integration-2PpI-bCm.mjs.map → integration-CeL90DtN.mjs.map} +1 -1
- package/dist/{logger-DWTPZ0c1.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-Di44utlp.mjs → middleware-Cdebyfdt.mjs} +3 -69
- package/dist/middleware-Cdebyfdt.mjs.map +1 -0
- package/dist/{middleware-CjVyGyrG.d.mts → middleware-fbtEs6bq.d.mts} +2 -2
- package/dist/{middleware-CjVyGyrG.d.mts.map → middleware-fbtEs6bq.d.mts.map} +1 -1
- package/dist/nestjs/index.d.mts +2 -2
- 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 +4 -4
- package/dist/next/index.mjs +3 -3
- package/dist/next/instrumentation/create.d.mts +1 -1
- package/dist/next/instrumentation/create.mjs +1 -1
- package/dist/next/instrumentation.d.mts +1 -1
- package/dist/next/stream.d.mts +1 -1
- package/dist/nitro/errorHandler.mjs +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.mjs +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 +1 -1
- package/dist/{nitro--E4op34w.d.mts → nitro-CcN7HDnr.d.mts} +2 -2
- package/dist/{nitro--E4op34w.d.mts.map → nitro-CcN7HDnr.d.mts.map} +1 -1
- package/dist/{nitro-ClHmVj1H.mjs → nitro-DYFCSlho.mjs} +2 -2
- package/dist/{nitro-ClHmVj1H.mjs.map → nitro-DYFCSlho.mjs.map} +1 -1
- package/dist/{nitroConfigBridge-BkVWnSV3.mjs → nitroConfigBridge-lHPsE5zG.mjs} +8 -6
- package/dist/nitroConfigBridge-lHPsE5zG.mjs.map +1 -0
- package/dist/{nodeResponse-DKrYWrxk.mjs → nodeResponse-Dsl7gZUf.mjs} +1 -1
- package/dist/{nodeResponse-DKrYWrxk.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 +2 -2
- package/dist/orpc/index.mjs +2 -2
- package/dist/{package-Bgs0VSDF.mjs → package-Drb3wqqt.mjs} +2 -2
- package/dist/package-Drb3wqqt.mjs.map +1 -0
- package/dist/{parseError-BwBg-iW4.d.mts → parseError-BmoJ7XeF.d.mts} +2 -2
- package/dist/parseError-BmoJ7XeF.d.mts.map +1 -0
- package/dist/react-router/index.d.mts +2 -2
- package/dist/react-router/index.mjs +3 -2
- package/dist/react-router/index.mjs.map +1 -1
- package/dist/{register-disk-snippet-B_JyhodL.mjs → register-disk-snippet-B5svlT8-.mjs} +1 -1
- package/dist/{register-disk-snippet-B_JyhodL.mjs.map → register-disk-snippet-B5svlT8-.mjs.map} +1 -1
- 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/utils/parseError.d.mts +2 -2
- package/dist/{storage-D4sBVffQ.mjs → storage-BeFdoGTI.mjs} +1 -1
- package/dist/{storage-D4sBVffQ.mjs.map → storage-BeFdoGTI.mjs.map} +1 -1
- 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 +2 -2
- package/dist/sveltekit/index.mjs +5 -4
- package/dist/sveltekit/index.mjs.map +1 -1
- package/dist/toolkit.d.mts +5 -5
- package/dist/toolkit.mjs +7 -6
- package/dist/types.d.mts +1 -1
- package/dist/{useLogger-DiRWGD33.d.mts → useLogger-BupVLO9_.d.mts} +2 -2
- package/dist/{useLogger-DiRWGD33.d.mts.map → useLogger-BupVLO9_.d.mts.map} +1 -1
- package/dist/{utils-XPMPENUK.d.mts → utils-D_LY-J1k.d.mts} +2 -2
- package/dist/{utils-XPMPENUK.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 +1 -1
- package/dist/workers.mjs +1 -1
- package/package.json +17 -2
- package/dist/audit-CL0q7GJU.mjs.map +0 -1
- package/dist/fork-Di44utlp.mjs.map +0 -1
- package/dist/logger-DWTPZ0c1.d.mts.map +0 -1
- package/dist/nitroConfigBridge-BkVWnSV3.mjs.map +0 -1
- package/dist/package-Bgs0VSDF.mjs.map +0 -1
- package/dist/parseError-BwBg-iW4.d.mts.map +0 -1
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,5 +1,5 @@
|
|
|
1
|
-
import { l as AuditableLogger } from "../audit-
|
|
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
|
//#region src/sveltekit/index.d.ts
|
|
4
4
|
declare const useLogger: <T extends object = Record<string, unknown>>() => AuditableLogger<T>;
|
|
5
5
|
type EvlogSvelteKitOptions = BaseEvlogOptions;
|
package/dist/sveltekit/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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
|
|
7
|
-
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";
|
|
8
9
|
//#region src/sveltekit/index.ts
|
|
9
10
|
const { storage, useLogger } = createLoggerStorage("handle context. Make sure evlog() handle is added to your hooks.server.ts.");
|
|
10
11
|
registerDiskPrettyErrorSnippetReader();
|
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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 { $ 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-
|
|
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
|
package/dist/toolkit.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as definePlugin, M as enricherPlugin, N as getEmptyPluginRunner, j as drainPlugin, k as createPluginRunner } from "./audit-BXCYMjcC.mjs";
|
|
2
2
|
import { i as normalizeNumber, n as extractSafeNodeHeaders, r as getHeader, t as extractSafeHeaders } from "./headers-VtmnWcfn.mjs";
|
|
3
3
|
import { t as extractErrorStatus } from "./errors-DA0cyr8q.mjs";
|
|
4
4
|
import { n as toLoggerConfig, r as toMiddlewareOptions, t as defineEvlog } from "./define-Bpaymi-h.mjs";
|
|
5
5
|
import { n as shouldLog, t as getServiceForPath } from "./routes-4rMzRyTk.mjs";
|
|
6
6
|
import { n as isStreamingResponse, r as shouldDeferEmitForResponse, t as bindStreamingResponseLifecycle } from "./streamResponse-CmQ3qUbF.mjs";
|
|
7
|
-
import { i as withEvlogIdentityHeaders, n as EVLOG_VERSION, r as httpPost, t as EVLOG_USER_AGENT } from "./http-
|
|
8
|
-
import { a as getRuntimeConfig, i as formatPublicEnvKeys, n as defineHttpDrain, o as resolveAdapterConfig, r as applyDeprecatedAlias, t as defineDrain } from "./drain-
|
|
7
|
+
import { i as withEvlogIdentityHeaders, n as EVLOG_VERSION, r as httpPost, t as EVLOG_USER_AGENT } from "./http-pKfd8UDu.mjs";
|
|
8
|
+
import { a as getRuntimeConfig, i as formatPublicEnvKeys, n as defineHttpDrain, o as resolveAdapterConfig, r as applyDeprecatedAlias, t as defineDrain } from "./drain-Dl2ZJKRA.mjs";
|
|
9
9
|
import { n as toOtlpAttributeValue, r as toTypedAttributeValue, t as mergeEventField } from "./event-qwAv-7AZ.mjs";
|
|
10
10
|
import { n as OTEL_SEVERITY_TEXT, t as OTEL_SEVERITY_NUMBER } from "./severity-CwXUSHt3.mjs";
|
|
11
11
|
import { a as composePlugins, i as composeKeep, n as composeDrains, r as composeEnrichers, t as defineEnricher } from "./enricher-DAWf2-Fx.mjs";
|
|
12
|
-
import {
|
|
13
|
-
import { t as
|
|
14
|
-
import { t as
|
|
12
|
+
import { n as resolveMiddlewarePluginRunner, r as runEnrichAndDrain, t as createMiddlewareLogger } from "./middleware-Cdebyfdt.mjs";
|
|
13
|
+
import { n as forkBackgroundLogger, t as attachForkToLogger } from "./fork-S9gpZmF8.mjs";
|
|
14
|
+
import { t as defineFrameworkIntegration } from "./integration-CeL90DtN.mjs";
|
|
15
|
+
import { t as createLoggerStorage } from "./storage-BeFdoGTI.mjs";
|
|
15
16
|
export { EVLOG_USER_AGENT, EVLOG_VERSION, OTEL_SEVERITY_NUMBER, OTEL_SEVERITY_TEXT, 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 };
|
package/dist/types.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as LogLevel, B as AuditTarget, F as AuditChanges, G as EnvironmentContext, H as DeepPartial, I as AuditFields, J as FieldContext, K as ErrorCode, L as AuditLoggerMethod, M as AuditAction, N as AuditActionDefinition, P as AuditActor, Q as Log, R as AuditPatchOp, U as DrainContext, V as BaseWideEvent, W as EnrichContext, X as IngestPayload, Y as H3EventContext, Z as InternalFields, at as RequestLogEntry, ct as RouteConfig, dt as ServerEvent, et as LoggerConfig, ft as TailSamplingCondition, ht as WideEvent, it as RegisteredErrorCatalogs, lt as SamplingConfig, mt as TransportConfig, nt as RedactConfig, ot as RequestLogger, pt as TailSamplingContext, q as ErrorOptions, rt as RegisteredAuditCatalogs, st as RequestLoggerOptions, tt as ParsedError, ut as SamplingRates, z as AuditSeverity } from "./audit-
|
|
1
|
+
import { $ as LogLevel, B as AuditTarget, F as AuditChanges, G as EnvironmentContext, H as DeepPartial, I as AuditFields, J as FieldContext, K as ErrorCode, L as AuditLoggerMethod, M as AuditAction, N as AuditActionDefinition, P as AuditActor, Q as Log, R as AuditPatchOp, U as DrainContext, V as BaseWideEvent, W as EnrichContext, X as IngestPayload, Y as H3EventContext, Z as InternalFields, at as RequestLogEntry, ct as RouteConfig, dt as ServerEvent, et as LoggerConfig, ft as TailSamplingCondition, ht as WideEvent, it as RegisteredErrorCatalogs, lt as SamplingConfig, mt as TransportConfig, nt as RedactConfig, ot as RequestLogger, pt as TailSamplingContext, q as ErrorOptions, rt as RegisteredAuditCatalogs, st as RequestLoggerOptions, tt as ParsedError, ut as SamplingRates, z as AuditSeverity } from "./audit-BZrUvjfW.mjs";
|
|
2
2
|
export { AuditAction, AuditActionDefinition, AuditActor, AuditChanges, AuditFields, AuditLoggerMethod, AuditPatchOp, AuditSeverity, AuditTarget, BaseWideEvent, DeepPartial, DrainContext, EnrichContext, EnvironmentContext, ErrorCode, ErrorOptions, FieldContext, H3EventContext, IngestPayload, InternalFields, Log, LogLevel, LoggerConfig, ParsedError, RedactConfig, RegisteredAuditCatalogs, RegisteredErrorCatalogs, RequestLogEntry, RequestLogger, RequestLoggerOptions, RouteConfig, SamplingConfig, SamplingRates, ServerEvent, TailSamplingCondition, TailSamplingContext, TransportConfig, WideEvent };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { dt as ServerEvent, l as AuditableLogger } from "./audit-
|
|
1
|
+
import { dt as ServerEvent, l as AuditableLogger } from "./audit-BZrUvjfW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/server/useLogger.d.ts
|
|
4
4
|
/**
|
|
@@ -36,4 +36,4 @@ import { dt as ServerEvent, l as AuditableLogger } from "./audit-CBfv3rl1.mjs";
|
|
|
36
36
|
declare function useLogger<T extends object = Record<string, unknown>>(event: ServerEvent, service?: string): AuditableLogger<T>;
|
|
37
37
|
//#endregion
|
|
38
38
|
export { useLogger as t };
|
|
39
|
-
//# sourceMappingURL=useLogger-
|
|
39
|
+
//# sourceMappingURL=useLogger-BupVLO9_.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLogger-
|
|
1
|
+
{"version":3,"file":"useLogger-BupVLO9_.d.mts","names":[],"sources":["../src/runtime/server/useLogger.ts"],"mappings":";;;;AAmCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,SAAA,oBAA6B,MAAA,kBAAA,CAAyB,KAAA,EAAO,WAAA,EAAa,OAAA,YAAmB,eAAA,CAAgB,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as LogLevel, G as EnvironmentContext } from "./audit-
|
|
1
|
+
import { $ as LogLevel, G as EnvironmentContext } from "./audit-BZrUvjfW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/utils.d.ts
|
|
4
4
|
declare function formatDuration(ms: number): string;
|
|
@@ -69,4 +69,4 @@ declare function globToRegExp(pattern: string, separator?: '/' | '.'): RegExp;
|
|
|
69
69
|
declare function matchesPattern(path: string, pattern: string): boolean;
|
|
70
70
|
//#endregion
|
|
71
71
|
export { matchesPattern as _, escapeFormatString as a, getConsoleMethod as c, globToRegExp as d, isBrowser as f, isServer as g, isLevelEnabled as h, detectEnvironment as i, getCssLevelColor as l, isDev as m, colors as n, filterSafeHeaders as o, isClient as p, cssColors as r, formatDuration as s, SENSITIVE_HEADERS as t, getLevelColor as u };
|
|
72
|
-
//# sourceMappingURL=utils-
|
|
72
|
+
//# sourceMappingURL=utils-D_LY-J1k.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils-
|
|
1
|
+
{"version":3,"file":"utils-D_LY-J1k.d.mts","names":[],"sources":["../src/utils.ts"],"mappings":";;;iBAEgB,cAAA,CAAe,EAAA;AAAA,iBAOf,QAAA,CAAA;AAAA,iBAIA,QAAA,CAAA;AAAA,iBAIA,SAAA,CAAA;AAAA,iBAOA,KAAA,CAAA;AAAA,iBAUA,iBAAA,CAAA,GAAqB,OAAA,CAAQ,kBAAA;;AAzB7C;;iBAsDgB,cAAA,CAAe,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,QAAA;AAAA,iBAI1C,gBAAA,CAAiB,KAAA,EAAO,QAAA,GAAW,QAAA;AAAA,cAItC,MAAA;EAAA;;;;;;;;;;;;iBAgBG,aAAA,CAAc,KAAA;AAAA,cAIjB,SAAA;EAAA;;;;;;;;iBAYG,gBAAA,CAAiB,KAAA;;;;;;iBASjB,kBAAA,CAAmB,GAAA;;cAKtB,iBAAA;;;;;;;;;AA9Cb;iBAkEgB,iBAAA,CAAkB,OAAA,EAAS,OAAA,CAAQ,MAAA,gCAAsC,MAAA;;;;;;;;iBAqBzE,YAAA,CAAa,OAAA,UAAiB,SAAA,eAA6B,MAAA;;;;;iBAsB3D,cAAA,CAAe,IAAA,UAAc,OAAA"}
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as matchesPattern, a as escapeFormatString, c as getConsoleMethod, d as globToRegExp, f as isBrowser, g as isServer, h as isLevelEnabled, i as detectEnvironment, l as getCssLevelColor, m as isDev, n as colors, o as filterSafeHeaders, p as isClient, r as cssColors, s as formatDuration, t as SENSITIVE_HEADERS, u as getLevelColor } from "./utils-
|
|
1
|
+
import { _ as matchesPattern, a as escapeFormatString, c as getConsoleMethod, d as globToRegExp, f as isBrowser, g as isServer, h as isLevelEnabled, i as detectEnvironment, l as getCssLevelColor, m as isDev, n as colors, o as filterSafeHeaders, p as isClient, r as cssColors, s as formatDuration, t as SENSITIVE_HEADERS, u as getLevelColor } from "./utils-D_LY-J1k.mjs";
|
|
2
2
|
export { SENSITIVE_HEADERS, colors, cssColors, detectEnvironment, escapeFormatString, filterSafeHeaders, formatDuration, getConsoleMethod, getCssLevelColor, getLevelColor, globToRegExp, isBrowser, isClient, isDev, isLevelEnabled, isServer, matchesPattern };
|
package/dist/vite/index.d.mts
CHANGED
package/dist/workers.d.mts
CHANGED
package/dist/workers.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as createRequestLogger, x as initLogger } from "./audit-
|
|
1
|
+
import { _ as createRequestLogger, x as initLogger } from "./audit-BXCYMjcC.mjs";
|
|
2
2
|
//#region src/workers/index.ts
|
|
3
3
|
function isRecord(value) {
|
|
4
4
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evlog",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0",
|
|
4
4
|
"description": "Modern TypeScript logger — simple logs, wide events, structured errors. Built for scripts, libraries, jobs, edge, and HTTP. One drain pipeline everywhere.",
|
|
5
5
|
"author": "HugoRCD <contact@hrcd.fr>",
|
|
6
6
|
"homepage": "https://evlog.dev",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"elysia",
|
|
26
26
|
"nestjs",
|
|
27
27
|
"orpc",
|
|
28
|
+
"eve",
|
|
28
29
|
"sveltekit",
|
|
29
30
|
"react-router",
|
|
30
31
|
"vite",
|
|
@@ -194,6 +195,11 @@
|
|
|
194
195
|
"import": "./dist/orpc/index.mjs",
|
|
195
196
|
"default": "./dist/orpc/index.mjs"
|
|
196
197
|
},
|
|
198
|
+
"./eve": {
|
|
199
|
+
"types": "./dist/eve/index.d.mts",
|
|
200
|
+
"import": "./dist/eve/index.mjs",
|
|
201
|
+
"default": "./dist/eve/index.mjs"
|
|
202
|
+
},
|
|
197
203
|
"./react-router": {
|
|
198
204
|
"types": "./dist/react-router/index.d.mts",
|
|
199
205
|
"import": "./dist/react-router/index.mjs",
|
|
@@ -327,6 +333,9 @@
|
|
|
327
333
|
"orpc": [
|
|
328
334
|
"./dist/orpc/index.d.mts"
|
|
329
335
|
],
|
|
336
|
+
"eve": [
|
|
337
|
+
"./dist/eve/index.d.mts"
|
|
338
|
+
],
|
|
330
339
|
"react-router": [
|
|
331
340
|
"./dist/react-router/index.d.mts"
|
|
332
341
|
],
|
|
@@ -365,6 +374,7 @@
|
|
|
365
374
|
"@nuxt/test-utils": "^4.0.3",
|
|
366
375
|
"@orpc/client": "^1.14.2",
|
|
367
376
|
"@orpc/server": "^1.14.2",
|
|
377
|
+
"ai": "^7.0.0",
|
|
368
378
|
"@stryker-mutator/core": "^9.6.1",
|
|
369
379
|
"@stryker-mutator/vitest-runner": "^9.6.1",
|
|
370
380
|
"@sveltejs/kit": "^2.59.0",
|
|
@@ -377,6 +387,7 @@
|
|
|
377
387
|
"changelogen": "^0.6.2",
|
|
378
388
|
"consola": "^3.4.2",
|
|
379
389
|
"elysia": "^1.4.28",
|
|
390
|
+
"eve": "^0.12.3",
|
|
380
391
|
"express": "^5.2.1",
|
|
381
392
|
"fastify": "^5.8.5",
|
|
382
393
|
"h3": "^1.15.11",
|
|
@@ -401,8 +412,9 @@
|
|
|
401
412
|
"@nestjs/common": ">=11.1.19",
|
|
402
413
|
"@nuxt/kit": "^4.4.2",
|
|
403
414
|
"@orpc/server": ">=1.14.0",
|
|
415
|
+
"eve": ">=0.12.0",
|
|
404
416
|
"@tanstack/start-client-core": "^1.167.20",
|
|
405
|
-
"ai": ">=6.0.168",
|
|
417
|
+
"ai": ">=6.0.168 <8.0.0",
|
|
406
418
|
"elysia": ">=1.4.28",
|
|
407
419
|
"express": ">=5.2.1",
|
|
408
420
|
"fastify": ">=5.8.5",
|
|
@@ -456,6 +468,9 @@
|
|
|
456
468
|
"@orpc/server": {
|
|
457
469
|
"optional": true
|
|
458
470
|
},
|
|
471
|
+
"eve": {
|
|
472
|
+
"optional": true
|
|
473
|
+
},
|
|
459
474
|
"react-router": {
|
|
460
475
|
"optional": true
|
|
461
476
|
},
|