JSPM

@rodrigopsasaki/vision-express

0.5.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 8
  • Score
    100M100P100Q31904F
  • License MIT

Express middleware for seamless Vision context integration

Package Exports

  • @rodrigopsasaki/vision-express

Readme

@rodrigopsasaki/vision-express

Express middleware for seamless Vision context integration. Automatically creates structured observability contexts for HTTP requests with intelligent defaults and simplified configuration.

Features

  • Just Works Out of the Box: No configuration required - intelligent defaults handle everything
  • Smart User Detection: Automatically detects users from common authentication patterns
  • Smart Correlation ID Detection: Finds correlation IDs from common headers
  • Security by Default: Sensitive data is automatically redacted
  • Automatic Context Creation: Every HTTP request gets wrapped in a Vision context
  • Comprehensive Metadata Capture: Request/response data, headers, timing, errors
  • Route Exclusion: Health checks and metrics endpoints excluded by default
  • TypeScript Support: Full type safety with extended Express interfaces
  • Error Handling: Automatic error capture and context preservation

Installation

npm install @rodrigopsasaki/vision-express
npm install @rodrigopsasaki/vision

Quick Start

import express from "express";
import { vision } from "@rodrigopsasaki/vision";
import { visionMiddleware } from "@rodrigopsasaki/vision-express";

const app = express();

// Initialize Vision with exporters
vision.init({
  exporters: [
    // Your exporters here
  ],
});

// Add the Vision middleware - just works out of the box!
app.use(visionMiddleware());

// Your routes now have automatic context tracking
app.get("/users/:id", async (req, res) => {
  // Add custom data to the context
  vision.set("user_id", req.params.id);
  vision.set("operation", "get_user");

  const user = await getUser(req.params.id);
  res.json(user);
});

API Reference

visionMiddleware(options?)

The recommended default middleware - just works out of the box with intelligent defaults.

import { visionMiddleware } from "@rodrigopsasaki/vision-express";

// Basic usage - no configuration needed
app.use(visionMiddleware());

// With custom options
app.use(
  visionMiddleware({
    captureBody: true,
    excludeRoutes: ["/health", "/metrics"],
    extractUser: (req) => req.headers["x-user-id"],
  }),
);

createVisionMiddleware(options?)

Creates a Vision Express middleware with custom configuration.

import { createVisionMiddleware } from "@rodrigopsasaki/vision-express";

app.use(
  createVisionMiddleware({
    captureBody: true,
    excludeRoutes: ["/health", "/metrics"],
    extractUser: (req) => req.user,
  }),
);

createMinimalVisionMiddleware()

Creates a middleware with no Express metadata capture - perfect for when you want Vision context but no Express clutter.

import { createMinimalVisionMiddleware } from "@rodrigopsasaki/vision-express";

app.use(createMinimalVisionMiddleware());

createComprehensiveVisionMiddleware()

Creates a middleware that captures all available data including request bodies (use with caution).

import { createComprehensiveVisionMiddleware } from "@rodrigopsasaki/vision-express";

app.use(createComprehensiveVisionMiddleware());

createSecureVisionMiddleware()

Creates a middleware with extra security redaction - perfect for high-security applications.

import { createSecureVisionMiddleware } from "@rodrigopsasaki/vision-express";

app.use(createSecureVisionMiddleware());

Configuration Options

Basic Options

Option Type Default Description
enabled boolean true Whether the middleware is enabled
excludeRoutes string[] ["/health", "/metrics", "/status", "/favicon.ico"] Routes to exclude from tracking
captureHeaders boolean true Capture request headers
captureQueryParams boolean true Capture query parameters
captureBody boolean false Capture request body (off by default for security)

Smart Detection Options

Option Type Default Description
extractUser (req) => unknown Smart detection Extract user from common patterns
correlationIdHeaders string[] Common headers Headers to check for correlation IDs

Security Options

Option Type Default Description
redactHeaders string[] Sensitive headers Headers to redact
redactQueryParams string[] Sensitive params Query params to redact
redactBodyFields string[] Sensitive fields Body fields to redact

Response Options

Option Type Default Description
includeRequestId boolean true Add request ID to response headers
requestIdHeader string X-Request-ID Header name for request ID

Smart Defaults

User Detection

The middleware automatically tries to extract user information from common patterns:

// Tries these in order:
req.user; // Passport.js, JWT middleware
req.session.user; // Session-based auth
req.headers["x-user-id"]; // Custom header
req.headers["x-user"]; // Custom header

Correlation ID Detection

Automatically finds correlation IDs from common headers:

// Tries these headers in order:
"x-correlation-id";
"x-request-id";
"x-trace-id";
"x-transaction-id";
"correlation-id";
"request-id";

Security Redaction

By default, these fields are automatically redacted:

Headers:

  • authorization
  • cookie
  • x-api-key
  • x-auth-token
  • x-session-token
  • x-csrf-token

Query Parameters:

  • token
  • key
  • secret
  • password
  • auth
  • api_key

Body Fields:

  • password
  • ssn
  • credit_card
  • secret
  • api_key
  • private_key

Usage Examples

import express from "express";
import { vision } from "@rodrigopsasaki/vision";
import { visionMiddleware } from "@rodrigopsasaki/vision-express";

const app = express();

// Initialize Vision
vision.init({
  exporters: [
    {
      name: "console",
      success: (ctx) => console.log("Request completed:", ctx),
      error: (ctx, err) => console.error("Request failed:", ctx, err),
    },
  ],
});

// Add middleware - just works out of the box!
app.use(visionMiddleware());

// Your routes
app.get("/api/users/:id", async (req, res) => {
  vision.set("user_id", req.params.id);
  vision.set("operation", "get_user");

  const user = await getUser(req.params.id);
  res.json(user);
});

Custom Configuration

import express from "express";
import { visionMiddleware } from "@rodrigopsasaki/vision-express";

const app = express();

app.use(
  visionMiddleware({
    // Enable body capture for development
    captureBody: true,

    // Exclude additional routes
    excludeRoutes: ["/health", "/metrics", "/status", "/static", "/favicon.ico"],

    // Custom user extraction
    extractUser: (req) => (req as any).user || req.headers["x-user-id"],

    // Custom correlation ID headers
    correlationIdHeaders: ["x-correlation-id", "x-request-id", "x-trace-id"],

    // Additional security redaction
    redactHeaders: [
      "authorization",
      "cookie",
      "x-api-key",
      "x-auth-token",
      "x-session-token",
      "x-csrf-token",
    ],
    redactQueryParams: ["token", "key", "secret", "password", "auth"],
    redactBodyFields: ["password", "ssn", "credit_card", "secret", "api_key"],
  }),
);

Different Middleware Options

import express from "express";
import {
  visionMiddleware,
  createMinimalVisionMiddleware,
  createComprehensiveVisionMiddleware,
  createSecureVisionMiddleware,
} from "@rodrigopsasaki/vision-express";

const app = express();

// Option 1: Simple Vision (default) - just works out of the box
app.use(visionMiddleware());

// Option 2: Minimal Vision - no Express metadata clutter
app.use(createMinimalVisionMiddleware());

// Option 3: Comprehensive Vision - everything including body
app.use(createComprehensiveVisionMiddleware());

// Option 4: Secure Vision - extra security protection
app.use(createSecureVisionMiddleware());

Accessing Context in Routes

import type { VisionRequest } from "@rodrigopsasaki/vision-express";

app.get("/users/:id", async (req: VisionRequest, res) => {
  // Access the Vision context
  const ctx = req.visionContext;
  console.log("Request ID:", ctx.id);

  // Add data to the context
  vision.set("user_id", req.params.id);
  vision.set("operation", "get_user");
  vision.set("timestamp", new Date().toISOString());

  // Add structured data
  vision.merge("request", {
    method: req.method,
    path: req.path,
    query: req.query,
  });

  // Add to arrays
  vision.push("events", "user_lookup_started");

  const user = await getUser(req.params.id);

  vision.push("events", "user_lookup_completed");
  vision.set("result_count", 1);

  res.json(user);
});

Testing with Headers

# Basic request
curl http://localhost:3000/users/123

# With correlation ID
curl -H "X-Correlation-ID: test-123" http://localhost:3000/users/123

# With user context
curl -H "X-User-ID: user-456" http://localhost:3000/users/123

# With sensitive data (automatically redacted)
curl -H "Authorization: Bearer secret-token" \
     -H "Cookie: session=abc123" \
     "http://localhost:3000/users/123?token=secret&password=123456"

Captured Data

The middleware automatically captures the following data:

Request Data

  • HTTP method and path
  • Request headers (with automatic redaction)
  • Query parameters (with automatic redaction)
  • Request body (optional, with automatic redaction)
  • Correlation ID (if found in headers)
  • User information (if found)

Response Data

  • Status code
  • Response headers
  • Duration (timing)

TypeScript Support

The package provides extended Express interfaces:

import type { VisionRequest, VisionResponse } from "@rodrigopsasaki/vision-express";

app.get("/users/:id", (req: VisionRequest, res: VisionResponse) => {
  // req.visionContext is available
  const ctx = req.visionContext;

  // Add data to context
  vision.set("user_id", req.params.id);
});

Security Considerations

  • Request Bodies: Disabled by default to prevent logging sensitive data
  • Automatic Redaction: Common sensitive fields are redacted by default
  • Custom Redaction: Configure which fields to redact based on your needs
  • Route Exclusion: Health checks and metrics endpoints excluded by default

Best Practices

  1. Use Default Middleware: Start with visionMiddleware() - it just works
  2. Initialize Vision First: Always initialize Vision with exporters before adding the middleware
  3. Customize When Needed: Only configure options when you need to override defaults
  4. Use Route Exclusion: Add custom routes to exclude if needed
  5. Review Redaction: Ensure sensitive data is properly redacted for your use case
  6. Handle Errors Gracefully: Let Vision capture errors automatically
  7. Use TypeScript: Leverage the provided types for better development experience

Integration with Exporters

The middleware works seamlessly with any Vision exporter:

import { vision } from "@rodrigopsasaki/vision";
import { createDatadogExporter } from "@rodrigopsasaki/vision-datadog-exporter";

// Initialize with exporters
vision.init({
  exporters: [
    createDatadogExporter({
      apiKey: process.env.DATADOG_API_KEY,
      service: "my-api",
    }),
  ],
});

// Add middleware - just works!
app.use(visionMiddleware());

License

MIT