Skip to content

chore(repo): version packages#327

Merged
HugoRCD merged 1 commit intomainfrom
changeset-release/main
May 9, 2026
Merged

chore(repo): version packages#327
HugoRCD merged 1 commit intomainfrom
changeset-release/main

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented May 8, 2026

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

evlog@2.17.0

Minor Changes

  • #332 ced6eda Thanks @HugoRCD! - Tag every drain request with identity headers so receivers can recognize evlog traffic and the originating adapter without parsing the body.

    • User-Agent: evlog/<version> on Node / server runtimes (browsers strip User-Agent).
    • X-Evlog-Source: <adapter> (axiom, datadog, otlp, posthog, sentry, better-stack, hyperdx, client for browser-originated drains).
    • httpPost gains userAgent?: string | false and source?: string options so custom drains can override or suppress the headers.
    • New exports from evlog/toolkit: EVLOG_VERSION, EVLOG_USER_AGENT, withEvlogIdentityHeaders.

    Adapters built with defineHttpDrain() automatically forward their name as source. The legacy sendBatchTo* helpers in evlog/axiom, evlog/datadog, evlog/otlp, evlog/posthog, evlog/sentry, and evlog/better-stack pass it explicitly.

  • #325 6b06511 Thanks @HugoRCD! - Add typed error and audit catalogs as a thin layer over createError and defineAuditAction. Three new primitives, zero runtime registration, zero init step. The whole feature is opt-in: existing createError({ code, ... }) and defineAuditAction(...) call sites keep working unchanged, with no migration required.

    import { defineErrorCatalog, defineAuditCatalog } from "evlog";
    
    export const billingErrors = defineErrorCatalog("billing", {
      PAYMENT_DECLINED: {
        status: 402,
        message: "Card declined",
        why: "...",
        fix: "...",
        link: "...",
      },
      INSUFFICIENT_FUNDS: {
        status: 402,
        message: ({
          available,
          required,
        }: {
          available: number;
          required: number;
        }) => `Insufficient funds: $${available}/$${required}`,
      },
    });
    
    export const billingAudit = defineAuditCatalog("billing", {
      INVOICE_REFUND: { target: "invoice" },
      INVOICE_CREATE: { target: "invoice" },
    });
    
    throw billingErrors.PAYMENT_DECLINED({ cause: stripeErr });
    throw billingErrors.INSUFFICIENT_FUNDS({ available: 5, required: 100 });
    log.audit(billingAudit.INVOICE_REFUND({ actor, target: { id: "inv_889" } }));

    New API on the main evlog entrypoint:

    • defineError(code, options) — single-error factory bound to a stable code. Accepts every existing EvlogError field plus a tags array and an internal defaults object. message can be either a string or a typed function whose params become required at the call site.
    • defineErrorCatalog(prefix, map) — bundle a record of entries under a common prefix. The wire code for each entry is ${prefix}.${KEY} (UPPER_SNAKE_CASE keys preserved). Catalog metadata (_codes, _prefix) exposed for introspection.
    • defineAuditCatalog(prefix, map) — symmetric primitive for audit actions. Each entry produces a thin wrapper around defineAuditAction with the prefix and target type pre-applied. Exposes _actions and _prefix.

    Type-level upgrade (opt-in, zero runtime cost):

    • RegisteredErrorCatalogs and RegisteredAuditCatalogs interfaces (empty by default, augmentable via declare module 'evlog').
    • New ErrorCode and AuditAction types derived from registered catalogs.
    • ErrorOptions.code and ParsedError.code now typed as ErrorCode | (string & {}) — autocomplete on registered codes everywhere (createError, parseError, custom helpers) without breaking ad-hoc string usage.

    Catalog factories return regular EvlogError instances and AuditInput objects respectively, so they integrate transparently with every existing evlog primitive (HTTP serializers, parseError, wide event capture, audit pipeline, drains). Catalogs are pure data — package them as npm libraries (one prefix per package), and the typing flows transitively to consumers via the published .d.ts. No global init, no proxy, no string-based dispatch helper.

  • #332 ced6eda Thanks @HugoRCD! - Add readFsLogs() and tailFsLogs() to evlog/fs so any external Node tool can replay or follow the local NDJSON drain without hooking into the running app. The fs adapter has been write-only until now; this closes the loop.

    import { readFsLogs, tailFsLogs } from "evlog/fs";
    
    // Replay history (ends when the last file is read)
    for await (const event of readFsLogs({
      since: "2026-03-01",
      level: "error",
    })) {
      // ...
    }
    
    // Live tail (yields existing then keeps yielding new ones — abort via AbortSignal)
    const ac = new AbortController();
    for await (const event of tailFsLogs({ signal: ac.signal })) {
      // ...
    }

    Both helpers accept dir, since, until, level, and a custom filter predicate. tailFsLogs additionally takes pollIntervalMs, fromEnd, and signal. Files outside the date window are skipped without being opened, malformed lines are silently skipped, and partial-write chunks are reassembled across polls.

    Useful for post-incident triage scripts, Vitest e2e assertions on emitted wide events, replay-to-Axiom backfills, and grep-style CLIs that pipe filtered events into jq.

  • #332 ced6eda Thanks @HugoRCD! - Add a local Server-Sent Events stream server so any consumer (browser tab, CLI, devtool) can subscribe to live wide events without going through your app's API surface. The server runs in the same Node process on its own ephemeral port; the URL is printed at startup and written to .evlog/stream.url for tools to discover.

    Strict opt-in for the framework integrations: the Nuxt module and the Next.js defineStreamedInstrumentation helper only boot the server when stream: true (or a config object) is passed. startStreamServer() itself is always an explicit call — call it from any standalone script or framework wiring that doesn't have a built-in evlog config.

    Nuxt

    evlog: {
      stream: true,
      // or: stream: { port: 4317, token: process.env.EVLOG_STREAM_TOKEN }
    }

    Next.js — new helper in evlog/next/stream:

    import { defineStreamedInstrumentation } from "evlog/next/stream";
    
    export const { register, onRequestError } = defineStreamedInstrumentation({
      service: "my-app",
      stream: true,
    });

    Standalone / any framework:

    import { startStreamServer } from "evlog/stream";
    
    const server = await startStreamServer();
    // pass server.drain wherever you compose your evlog drain

    The Nuxt module also registers a tiny /api/_evlog/stream-info route that returns the mini-server URL so a same-origin browser tab can discover the ephemeral port.

    API surface in evlog/stream:

    • startStreamServer(options): Promise<StreamServer>node:http server bound to 127.0.0.1 by default, idempotent, lazy-imports Node-only modules so evlog/stream stays edge-friendly for the in-process primitive.
    • StreamServerOptions: port, host, token, heartbeatMs, buffer, banner, urlFileDir.
    • StreamServer: { url, port, drain, stream, close }.
    • Cleans up .evlog/stream.url and listeners on close() + SIGINT / SIGTERM / exit.

    Wire format is a versioned JSON envelope { evlog: "1", type, data } with frames hello, replay, event, and ping.

    Local-only by design. The server is in-process — on serverless platforms (Vercel Functions, Cloudflare Workers, AWS Lambda) each invocation is isolated, so a subscriber would only see events from its own isolate. Use a real broker for cross-instance fan-out in those environments.

Patch Changes

  • #335 fd830a0 Thanks @HugoRCD! - Documentation site restructured into 6 audience-driven categories: Start → Learn → Integrate → Use Cases → Extend → Reference. The npm-shipped README.md and a single JSDoc @see URL have been updated to point to the new locations.

    Old documentation URLs continue to work via 301 redirects defined in apps/docs/config/redirects.ts. No public API changed.

    If you bookmarked specific documentation pages, the most common moves are:

    • /getting-started/*/start/*
    • /logging/{simple-logging,wide-events,structured-errors}/learn/*
    • /logging/{ai-sdk,better-auth,audit,client-logging}/*/use-cases/*
    • /core-concepts/{lifecycle,sampling,typed-fields,redaction}/learn/*
    • /core-concepts/{configuration,performance,vite-plugin,best-practices}/reference/*
    • /frameworks/*/integrate/frameworks/*
    • /adapters/*/integrate/adapters/*
    • /build-on-top/*/extend/*
    • /enrichers/*/use-cases/enrichers or /extend/custom-enrichers
  • #336 872f150 Thanks @HugoRCD! - Fix wide event never being emitted when the client disconnects mid-request in evlog/express and evlog/nestjs.

    Both integrations now listen for the underlying socket close event in addition to finish. When the client aborts before res.end() resolves, the wide event is still emitted (with the same status, duration, and accumulated context) and tagged with connectionClosed: true so disconnects are observable in your drain. The first event to fire wins, so successful responses are unaffected.

    For background work that must outlive the HTTP response (resumable streams, post-response usage accounting), continue to use req.log.fork('label', fn) — once the request logger has been emitted it is sealed.

    Closes #305.

evlog-community-adapter-skeleton@3.0.0

Patch Changes

evlog-community-enricher-skeleton@3.0.0

Patch Changes

evlog-community-framework-skeleton@3.0.0

Patch Changes

@vercel
Copy link
Copy Markdown

vercel Bot commented May 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
evlog-docs Ready Ready Preview, Comment, Open in v0 May 9, 2026 9:25pm
just-use-evlog Ready Ready Preview, Comment May 9, 2026 9:25pm

@github-actions github-actions Bot force-pushed the changeset-release/main branch from c8c8582 to 4c7d8be Compare May 9, 2026 11:41
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 4c7d8be to 203bb9b Compare May 9, 2026 11:43
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 203bb9b to e6e775f Compare May 9, 2026 17:12
@github-actions github-actions Bot force-pushed the changeset-release/main branch from e6e775f to 0b4e2c4 Compare May 9, 2026 17:28
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 0b4e2c4 to 3c4764b Compare May 9, 2026 17:52
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 3c4764b to 62f9c84 Compare May 9, 2026 18:01
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 62f9c84 to 2593934 Compare May 9, 2026 21:05
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 2593934 to d97828c Compare May 9, 2026 21:23
@HugoRCD HugoRCD merged commit db45884 into main May 9, 2026
4 checks passed
@HugoRCD HugoRCD deleted the changeset-release/main branch May 9, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Wide event is never emitted when the client disconnects

1 participant