npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@rodrigopsasaki/vision-koa

v0.5.0

Published

Elegant Koa middleware for seamless Vision context integration

Readme

🎯 @rodrigopsasaki/vision-koa

Elegant Koa middleware for seamless Vision context integration. Designed for simplicity, built for observability.

✨ Features

  • 🧘 Zen-like simplicity - Fits Koa's minimalist philosophy
  • 🎯 Automatic context creation - Every request gets a Vision context
  • Async/await native - Built for modern async patterns
  • 🔒 Security-first - Smart sensitive data redaction
  • 🎨 Highly configurable - From minimal to comprehensive tracking
  • 🔄 Middleware composable - Works with all Koa middleware
  • 📊 Rich metadata capture - State, cookies, headers, and more
  • 🏗️ TypeScript first - Full type safety and IntelliSense

🚀 Quick Start

npm install @rodrigopsasaki/vision @rodrigopsasaki/vision-koa
import Koa from "koa";
import { createVisionMiddleware } from "@rodrigopsasaki/vision-koa";

const app = new Koa();

// Register the Vision middleware
app.use(createVisionMiddleware());

app.use(async (ctx, next) => {
  // Vision context is automatically available
  vision.set("user_id", ctx.params?.id);
  vision.set("operation", "get_data");

  ctx.body = { message: "Hello, World!" };
});

app.listen(3000);

🎛️ Configuration Options

Basic Configuration

app.use(
  createVisionMiddleware({
    // Data capture options
    captureHeaders: true,
    captureBody: false, // Be careful in production
    captureQuery: true,
    captureParams: true,

    // Performance tracking
    performance: {
      trackExecutionTime: true,
      slowOperationThreshold: 1000, // 1 second
      trackMemoryUsage: false,
    },

    // Security & privacy
    redactSensitiveData: true,
    redactHeaders: ["authorization", "cookie"],
    redactQueryParams: ["token", "password"],
    redactBodyFields: ["password", "ssn"],
  }),
);

Advanced Configuration

app.use(
  createVisionMiddleware({
    // Custom extractors
    extractUser: (ctx) => ({
      id: ctx.headers["x-user-id"],
      role: ctx.state.userRole,
    }),

    extractCorrelationId: (ctx) => ctx.headers["x-correlation-id"] || ctx.headers["x-request-id"],

    extractMetadata: (ctx) => ({
      client_version: ctx.headers["x-client-version"],
      session_id: ctx.cookies.get("session_id"),
      feature_flags: ctx.state.featureFlags,
    }),

    // Custom context naming
    contextNameGenerator: (ctx) => `api.${ctx.method.toLowerCase()}.${ctx.path}`,

    // Route exclusion
    excludeRoutes: ["/health", "/metrics", "/docs/*"],
    shouldExcludeRoute: (ctx) => ctx.path.startsWith("/internal/"),
  }),
);

🎨 Pre-configured Middleware

Minimal Middleware (Performance Optimized)

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

app.use(
  createMinimalVisionMiddleware({
    performance: { slowOperationThreshold: 100 },
  }),
);

Comprehensive Middleware (Full Observability)

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

app.use(
  createComprehensiveVisionMiddleware({
    captureBody: true,
    performance: { trackMemoryUsage: true },
  }),
);

Performance Middleware (Ultra-fast)

import { createPerformanceVisionMiddleware } from "@rodrigopsasaki/vision-koa";

app.use(createPerformanceVisionMiddleware());

Secure Middleware (Enhanced Security)

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

app.use(
  createSecureVisionMiddleware({
    // Automatically configured for maximum security
    captureBody: false,
    redactSensitiveData: true,
  }),
);

📊 Vision API Usage

Use the full power of Vision's API within your middleware:

app.use(async (ctx, next) => {
  // Set operation context
  vision.set("operation", "create_order");
  vision.set("user_id", ctx.state.userId);

  // Track business events
  vision.push("events", {
    event: "order_started",
    user_id: ctx.state.userId,
    timestamp: new Date().toISOString(),
  });

  await next();

  // Track completion
  vision.push("events", {
    event: "order_completed",
    order_id: ctx.body.orderId,
    timestamp: new Date().toISOString(),
  });
});

app.use(async (ctx, next) => {
  // Add business context
  vision.merge("business_context", {
    operation: "payment_processing",
    customer_tier: ctx.state.user?.tier,
    payment_method: ctx.request.body?.paymentMethod,
  });

  // Track performance of external calls
  const startTime = Date.now();
  const paymentResult = await processPayment(ctx.request.body);

  vision.push("external_api_calls", {
    service: "payment-gateway",
    duration_ms: Date.now() - startTime,
    success: paymentResult.success,
  });

  ctx.body = { orderId: paymentResult.orderId };
});

🔍 Context Access

Access the Vision context throughout your middleware stack:

// In route handlers
app.use(async (ctx, next) => {
  const visionCtx = ctx.visionContext;
  if (visionCtx) {
    console.log("Context ID:", visionCtx.id);
    console.log("Context Data:", Object.fromEntries(visionCtx.data.entries()));
  }
  await next();
});

// In authentication middleware
app.use(async (ctx, next) => {
  const token = ctx.headers.authorization;
  const user = await authenticate(token);

  if (ctx.visionContext) {
    vision.merge("auth", {
      authenticated: !!user,
      user_id: user?.id,
      auth_method: "bearer_token",
    });
  }

  ctx.state.user = user;
  await next();
});

// In error handling middleware
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (error) {
    if (ctx.visionContext) {
      vision.push("error_events", {
        error_type: error.constructor.name,
        error_message: error.message,
        timestamp: new Date().toISOString(),
      });
    }
    throw error;
  }
});

⚡ Performance Tracking

Automatic performance insights:

// Slow operations are automatically detected
app.use(async (ctx, next) => {
  await generateComplexReport(); // Takes 2 seconds
  // Vision automatically marks this as slow_operation: true
  ctx.body = { report: "generated" };
});

// Custom performance tracking
app.use(async (ctx, next) => {
  const dbStart = Date.now();
  const users = await db.users.findMany();

  vision.push("performance", {
    operation: "database.users.findMany",
    duration_ms: Date.now() - dbStart,
    result_count: users.length,
  });

  ctx.body = { users };
});

🔒 Security & Privacy

Built-in security features:

app.use(
  createVisionMiddleware({
    // Automatic sensitive data redaction
    redactSensitiveData: true,
    redactHeaders: ["authorization", "cookie", "x-api-key", "x-auth-token"],
    redactQueryParams: ["token", "password", "secret", "api_key"],
    redactBodyFields: ["password", "ssn", "creditCard", "bankAccount"],

    // Custom error transformation
    errorHandling: {
      transformError: (error, ctx) => ({
        name: error.name,
        message: process.env.NODE_ENV === "production" ? "Internal server error" : error.message,
        // Never expose stack traces in production
        ...(process.env.NODE_ENV !== "production" && {
          stack: error.stack,
        }),
      }),
    },
  }),
);

📋 TypeScript Support

Full TypeScript integration with enhanced context types:

import type { VisionKoaContext } from "@rodrigopsasaki/vision-koa";

// Enhanced context with Vision integration
app.use(async (ctx: VisionKoaContext, next) => {
  // Full type safety
  const visionCtx = ctx.visionContext; // VisionContext | undefined
  const userId = ctx.params?.id; // Fully typed params

  // Vision context is fully typed
  if (visionCtx) {
    visionCtx.data.set("middleware_executed", true);
  }

  await next();
});

// Custom types with Vision context
interface CustomContext extends VisionKoaContext {
  state: {
    user?: { id: string; role: string };
    sessionId?: string;
  };
}

app.use(async (ctx: CustomContext, next) => {
  if (ctx.state.user && ctx.visionContext) {
    vision.set("user_role", ctx.state.user.role);
  }
  await next();
});

🧪 Testing

Vision-enabled testing utilities:

import request from "supertest";
import Koa from "koa";
import { createVisionMiddleware } from "@rodrigopsasaki/vision-koa";

const app = new Koa();
app.use(createVisionMiddleware());

app.use(async (ctx) => {
  ctx.body = { message: "test" };
});

describe("Vision Koa Integration", () => {
  it("should create Vision context", async () => {
    const response = await request(app.callback())
      .get("/test")
      .set("x-correlation-id", "test-correlation-123")
      .expect(200);

    expect(response.headers["x-request-id"]).toBeDefined();
    // You can add custom test exporters to verify context data
  });
});

🎯 Best Practices

Production Configuration

const isProduction = process.env.NODE_ENV === "production";

app.use(
  createVisionMiddleware({
    // Conservative settings for production
    captureHeaders: true,
    captureBody: false, // Avoid capturing sensitive data
    captureQuery: !isProduction, // Skip in production for performance

    // Stricter performance thresholds
    performance: {
      slowOperationThreshold: isProduction ? 500 : 1000,
      trackMemoryUsage: false, // Disable for performance
    },

    // Enhanced security
    redactSensitiveData: true,
    errorHandling: {
      captureStackTrace: !isProduction,
    },
  }),
);

Development Configuration

app.use(
  createComprehensiveVisionMiddleware({
    // Capture everything for debugging
    captureBody: true,
    captureHeaders: true,
    captureKoaMetadata: true,

    // Detailed error information
    errorHandling: {
      captureStackTrace: true,
      captureErrors: true,
    },

    // Sensitive performance tracking
    performance: {
      trackMemoryUsage: true,
      slowOperationThreshold: 100,
    },
  }),
);

Microservices Setup

app.use(
  createVisionMiddleware({
    // Propagate correlation IDs across services
    extractCorrelationId: (ctx) =>
      ctx.headers["x-correlation-id"] || ctx.headers["x-request-id"] || generateRequestId(),

    // Service-specific context naming
    contextNameGenerator: (ctx) => `order-service.${ctx.method.toLowerCase()}.${ctx.path}`,

    // Extract service metadata
    extractMetadata: (ctx) => ({
      service_name: "order-service",
      service_version: process.env.SERVICE_VERSION,
      deployment_env: process.env.NODE_ENV,
    }),
  }),
);

🔧 Advanced Usage

Conditional Middleware

// Only apply Vision to specific routes
app.use(async (ctx, next) => {
  if (ctx.path.startsWith("/api/")) {
    return createVisionMiddleware()(ctx, next);
  }
  await next();
});

Middleware Composition

// Compose with other middleware
app.use(createVisionMiddleware());
app.use(bodyParser());
app.use(cors());
app.use(helmet());

// Vision context is available in all downstream middleware
app.use(async (ctx, next) => {
  if (ctx.visionContext) {
    vision.set("middleware_stack", ["vision", "bodyParser", "cors", "helmet"]);
  }
  await next();
});

Router Integration

import Router from "@koa/router";

const router = new Router();

// Vision works seamlessly with koa-router
router.get("/users/:id", async (ctx) => {
  vision.set("user_id", ctx.params.id);
  vision.set("operation", "get_user");

  const user = await getUser(ctx.params.id);
  ctx.body = { user };
});

app.use(createVisionMiddleware());
app.use(router.routes());
app.use(router.allowedMethods());

Error Boundary Integration

// Global error handler with Vision integration
app.on("error", (error, ctx) => {
  if (ctx && ctx.visionContext) {
    vision.merge("error_boundary", {
      error_caught_by: "global_error_handler",
      error_type: error.constructor.name,
      timestamp: new Date().toISOString(),
    });
  }

  console.error("Global error:", error);
});

📦 Package Information

  • Bundle Size: Minimal footprint, optimized for Koa's simplicity
  • Dependencies: Only micromatch for pattern matching
  • TypeScript: Full type definitions included
  • Koa Support: v2.x
  • Node.js: v18+ recommended

🤝 Integration

Works seamlessly with:

  • @koa/router - Routing
  • @koa/cors - CORS handling
  • koa-helmet - Security headers
  • koa-bodyparser - Request body parsing
  • koa-jwt - JWT authentication
  • koa-compress - Response compression
  • koa-static - Static file serving
  • All other Koa middleware

📊 Comparison

| Feature | vision-express | vision-fastify | vision-koa | | ------------- | -------------- | -------------- | ---------------------- | | Philosophy | Minimal | Performance | Simplicity | | Async Support | Callback | Promise | Native Async/Await | | Type Safety | Good | Excellent | Excellent | | Bundle Size | Medium | Small | Smallest | | Configuration | Full | Full | Full | | Ecosystem | Large | Growing | Focused |

Perfect for modern APIs, microservices, and applications where simplicity and elegance are paramount! 🧘‍♂️