# SnapWyr - Full Documentation Context Zero-config HTTP request logger for Node.js with a real-time web dashboard. Log incoming and outgoing HTTP requests with beautiful console output and a live web UI. ## Key Links Homepage: https://snapwyr.xyz Documentation: https://snapwyr.xyz/docs npm: https://www.npmjs.com/package/snapwyr GitHub: https://github.com/emmanueltaiwo/snapwyr --- ## Installation URL: https://snapwyr.xyz/docs/getting-started/installation Description: Install Snapwyr in your Node.js project ### Content # Installation ## Requirements - Node.js >= 18 ## Install ```bash npm install snapwyr ``` ## Quick Start ### 1. Add Middleware Log incoming requests to your server: ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; const app = express(); app.use(snapwyr({ logBody: true })); ``` ### 2. Start the Dashboard View requests in your browser: ```javascript import { serve } from 'snapwyr/dashboard'; serve(3333); // http://localhost:3333 ``` ### 3. Log Outgoing Requests (Optional) Log requests your app makes to external APIs: ```javascript import { logRequests } from 'snapwyr'; // Log fetch requests (automatic) logRequests({ logBody: true }); // To log axios requests, pass your axios instance import axios from 'axios'; logRequests({ axios: axios, // Required for axios interception logBody: true, }); ``` ## Complete Example ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; import { logRequests } from 'snapwyr'; import { serve } from 'snapwyr/dashboard'; const app = express(); // Log incoming requests app.use(snapwyr({ logBody: true })); // Log outgoing requests logRequests({ logBody: true }); // To log axios requests, pass your axios instance import axios from 'axios'; logRequests({ axios: axios, // Required for axios interception logBody: true, }); // Start dashboard serve(3333); app.get('/api/users', (req, res) => { res.json([{ id: 1, name: 'John' }]); }); app.listen(3000, () => { console.log('Server: http://localhost:3000'); console.log('Dashboard: http://localhost:3333'); }); ``` ## Console Output ``` 12:34:56 GET 200 45ms /api/users 12:34:57 POST 201 89ms /api/users ``` ## Framework Support | Framework | Import | | --------- | ----------------- | | Express | `snapwyr/express` | | Fastify | `snapwyr/fastify` | | Koa | `snapwyr/koa` | | Hono | `snapwyr/hono` | | NestJS | `snapwyr/nestjs` | | Next.js | `snapwyr/nextjs` | See the [Framework Middleware](https://snapwyr.xyz/docs/getting-started/docs/guides/frameworks) guide for examples. --- ## Introduction URL: https://snapwyr.xyz/docs/getting-started/introduction Description: Learn what Snapwyr is and why you should use it ### Content # Introduction Snapwyr is a **zero-config HTTP request logger** for Node.js with a **real-time web dashboard**. Log incoming and outgoing HTTP requests with beautiful console output and a live web UI. ## What is Snapwyr? Snapwyr provides: - **Middleware** for logging incoming requests (Express, Fastify, Koa, Hono, NestJS, Next.js) - **Interceptors** for logging outgoing requests (fetch, axios - requires passing axios instance) - **Real-time dashboard** for viewing requests in your browser ## Quick Start ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; import { serve } from 'snapwyr/dashboard'; const app = express(); // Log all incoming requests app.use(snapwyr({ logBody: true })); // Start the dashboard serve(3333); app.listen(3000); ``` Open http://localhost:3333 to see the dashboard. ## Features ### Real-time Dashboard A web UI that shows all requests in real-time: - Live WebSocket updates - Filter by method, status, direction - Search by URL or body content - View request/response bodies - Copy requests as cURL commands ### Console Logging Color-coded console output: ``` 12:34:56 GET 200 45ms /api/users 12:34:57 POST 201 89ms /api/users 12:34:58 GET 404 12ms /api/unknown ``` ### Incoming and Outgoing Log both directions: - **Incoming** - Requests hitting your server (via middleware) - **Outgoing** - Requests your app makes to external APIs (via interceptors) ### Sensitive Data Redaction Automatically redact passwords, tokens, and API keys: ```javascript snapwyr({ logBody: true, redact: ['password', 'token', /api[_-]?key/i], }); ``` ### Request IDs Generate unique IDs for tracking requests: ```javascript snapwyr({ requestId: true, // Adds X-Request-ID header }); ``` ### Size Tracking See request and response sizes: ```javascript snapwyr({ sizeTracking: true, }); ``` ### cURL Export Copy any request as a cURL command from the dashboard for easy debugging. ## Framework Support | Framework | Import | Usage | | --------- | ----------------- | --------------------------- | | Express | `snapwyr/express` | `app.use(snapwyr())` | | Fastify | `snapwyr/fastify` | `fastify.register(snapwyr)` | | Koa | `snapwyr/koa` | `app.use(snapwyr())` | | Hono | `snapwyr/hono` | `app.use('*', snapwyr())` | | NestJS | `snapwyr/nestjs` | `SnapwyrInterceptor()` | | Next.js | `snapwyr/nextjs` | `snapwyr()` | ## Production Safety Snapwyr automatically disables itself when `NODE_ENV === 'production'`: ```javascript // In development: logs requests // In production: does nothing snapwyr(); ``` --- ## Basic Usage URL: https://snapwyr.xyz/docs/guides/basic-usage Description: Learn how to use Snapwyr to log HTTP requests ### Content # Basic Usage Snapwyr logs both incoming and outgoing HTTP requests with a real-time dashboard. ## Complete Example ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; import { logRequests } from 'snapwyr'; import { serve } from 'snapwyr/dashboard'; const app = express(); // Log incoming requests (to your server) app.use(snapwyr({ logBody: true })); // Log outgoing requests (to external APIs) logRequests({ logBody: true }); // Start dashboard at localhost:3333 serve(3333); app.get('/api/users', async (req, res) => { // This outgoing request is also logged const data = await fetch('https://api.github.com/users'); res.json(await data.json()); }); app.listen(3000); ``` ## Logging Incoming Requests Use middleware to log requests to your server. ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; const app = express(); app.use(snapwyr()); ``` **Console output:** ``` 12:34:56 GET 200 45ms /api/users 12:34:57 POST 201 89ms /api/users ``` ## Logging Outgoing Requests Log HTTP requests your app makes to external APIs. ```javascript import { logRequests } from 'snapwyr'; // Log fetch requests (automatic) logRequests(); const response = await fetch('https://api.example.com/users'); // To log axios requests, pass your axios instance import axios from 'axios'; logRequests({ axios: axios }); await axios.get('https://api.example.com/users'); ``` **Console output:** ``` 12:34:56 GET 200 234ms https://api.example.com/users ``` ## Using the Dashboard Start the dashboard to view requests in your browser. ```javascript import { serve } from 'snapwyr/dashboard'; serve(3333); // Open http://localhost:3333 ``` The dashboard shows: - All requests in real-time - Filter by method, status, direction - Search by URL or body - Request/response bodies - Copy as cURL ## Logging Bodies See what data is sent and received: ```javascript snapwyr({ logBody: true }); ``` ## Redacting Sensitive Data Hide passwords and tokens: ```javascript snapwyr({ logBody: true, redact: ['password', 'token', 'apiKey'], }); ``` Output shows `[REDACTED]` for matching fields. ## Filtering Requests ### Ignore URLs ```javascript snapwyr({ ignorePatterns: ['/health', '/metrics', /^\/_next/], }); ``` ### Filter by Method ```javascript snapwyr({ methods: ['POST', 'PUT', 'DELETE'], // Only mutations }); ``` ### Errors Only ```javascript snapwyr({ errorsOnly: true, // Only 4xx/5xx }); ``` ## Request IDs Generate unique IDs for tracing: ```javascript snapwyr({ requestId: true, // Adds X-Request-ID header }); ``` ## Size Tracking See request/response sizes: ```javascript snapwyr({ sizeTracking: true, }); ``` Output: ``` GET 200 45ms 2.4KB /api/users ``` ## Slow Request Detection Highlight slow requests: ```javascript snapwyr({ slowThreshold: 500, // Mark requests > 500ms }); ``` ## Custom Transport Send logs to external services: ```javascript snapwyr({ transport: (entry) => { fetch('https://logs.example.com', { method: 'POST', body: JSON.stringify(entry), }); }, }); ``` ## Stopping Logging ```javascript import { logRequests, stopLogging } from 'snapwyr'; logRequests(); // ... later stopLogging(); ``` --- ## Configuration URL: https://snapwyr.xyz/docs/guides/configuration Description: Configure Snapwyr to match your needs ### Content # Configuration Snapwyr accepts an optional configuration object to customize its behavior. ## All Options ```typescript interface SnapWyrConfig { // Output format?: 'pretty' | 'json'; // Log format (default: 'pretty') emoji?: boolean; // Show emoji indicators silent?: boolean; // Disable console output prefix?: string; // Prefix for log lines showTimestamp?: boolean; // Show timestamps (default: true) // Body logging logBody?: boolean; // Log request/response bodies bodySizeLimit?: number; // Max body size in bytes (default: 10KB) // Filtering errorsOnly?: boolean; // Only log 4xx/5xx responses methods?: string[]; // Only log these HTTP methods statusCodes?: number[]; // Only log these status codes ignorePatterns?: (string | RegExp)[]; // URLs to ignore // Features slowThreshold?: number; // Mark slow requests (ms, default: 1000) requestId?: boolean; // Generate X-Request-ID headers sizeTracking?: boolean; // Track request/response sizes redact?: (string | RegExp)[]; // Patterns to redact from bodies // HTTP Clients (for logRequests only) axios?: any; // Axios instance to intercept (required for axios logging) // Advanced transport?: (entry: LogEntry) => void; // Custom log handler enabled?: boolean; // Enable/disable logging } ``` ## Output Options ### format Choose between pretty console output or JSON. ```javascript // Pretty output (default) snapwyr({ format: 'pretty' }); // Output: GET 200 45ms /api/users // JSON output snapwyr({ format: 'json' }); // Output: {"method":"GET","status":200,"duration":45,"url":"/api/users"} ``` ### prefix Add a prefix to all log lines. ```javascript snapwyr({ prefix: '[API]' }); // Output: [API] GET 200 45ms /api/users ``` ### silent Disable console output (useful when using transport only). ```javascript snapwyr({ silent: true, transport: (entry) => sendToExternalService(entry), }); ``` ## Body Logging ### logBody Enable logging of request and response bodies. ```javascript snapwyr({ logBody: true }); ``` ### bodySizeLimit Limit body size to prevent large payloads from flooding logs. ```javascript snapwyr({ logBody: true, bodySizeLimit: 5000, // 5KB max }); ``` ## Filtering ### errorsOnly Only log failed requests (4xx/5xx status codes). ```javascript snapwyr({ errorsOnly: true }); ``` ### methods Only log specific HTTP methods. ```javascript snapwyr({ methods: ['POST', 'PUT', 'DELETE'], // Only mutations }); ``` ### statusCodes Only log specific status codes. ```javascript snapwyr({ statusCodes: [500, 502, 503, 504], // Only server errors }); ``` ### ignorePatterns Ignore specific URLs or patterns. ```javascript snapwyr({ ignorePatterns: ['/health', '/metrics', /^\/_next/, /\.(jpg|png|css|js)$/], }); ``` ## Features ### slowThreshold Mark requests slower than a threshold (in milliseconds). ```javascript snapwyr({ slowThreshold: 500, // Mark requests > 500ms as slow }); ``` Slow requests are highlighted in console output and marked in the dashboard. ### requestId Generate unique request IDs. ```javascript snapwyr({ requestId: true }); ``` This adds an `X-Request-ID` header to responses and includes the ID in logs: ``` [m2x9k-a3b] GET 200 45ms /api/users ``` ### sizeTracking Track request and response sizes. ```javascript snapwyr({ sizeTracking: true }); ``` Output includes size information: ``` GET 200 45ms 2.4KB /api/users ``` ### redact Redact sensitive data from logged bodies. ```javascript snapwyr({ logBody: true, redact: [ 'password', 'token', 'secret', 'apiKey', /api[_-]?key/i, /authorization/i, ], }); ``` Matching fields are replaced with `[REDACTED]`: ```json { "password": "[REDACTED]", "email": "user@example.com" } ``` ## Advanced ### transport Custom log handler for sending logs to external services. ```javascript snapwyr({ transport: (entry) => { // Send to logging service fetch('https://logs.example.com', { method: 'POST', body: JSON.stringify(entry), }); }, }); ``` The `entry` object contains: ```typescript interface LogEntry { id: string; timestamp: string; method: string; url: string; status: number | undefined; duration: number; slow: boolean; error?: string; requestBody?: string; responseBody?: string; requestSize?: number; responseSize?: number; totalSize?: number; direction?: 'incoming' | 'outgoing'; } ``` ### enabled Explicitly enable or disable logging. ```javascript snapwyr({ enabled: process.env.DEBUG === 'true', }); ``` ## Complete Example ### Middleware Configuration ```javascript import { snapwyr } from 'snapwyr/express'; import { serve } from 'snapwyr/dashboard'; app.use( snapwyr({ // Output format: 'pretty', prefix: '[API]', showTimestamp: true, // Body logging logBody: true, bodySizeLimit: 10000, // Filtering ignorePatterns: ['/health', '/metrics'], methods: ['GET', 'POST', 'PUT', 'DELETE'], // Features slowThreshold: 1000, requestId: true, sizeTracking: true, redact: ['password', 'token', /secret/i], // Send to external service transport: (entry) => { if (entry.error || entry.slow) { alertService.notify(entry); } }, }) ); // Start dashboard serve(3333); ``` ### Outgoing Requests Configuration ```javascript import { logRequests } from 'snapwyr'; import axios from 'axios'; // Log fetch requests (automatic) logRequests({ logBody: true, format: 'pretty', }); // Log axios requests (requires passing instance) logRequests({ axios: axios, // Required for axios interception logBody: true, format: 'pretty', slowThreshold: 500, }); ``` --- ## Dashboard URL: https://snapwyr.xyz/docs/guides/dashboard Description: Real-time web dashboard for viewing HTTP requests ### Content # Dashboard Snapwyr includes a real-time web dashboard for viewing all HTTP requests in your browser. ## Quick Start ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; import { serve } from 'snapwyr/dashboard'; const app = express(); // Log incoming requests app.use(snapwyr({ logBody: true })); // Start dashboard on port 3333 serve(3333); app.listen(3000); ``` Open http://localhost:3333 to view the dashboard. ## Features ### Live Updates The dashboard uses WebSockets to show requests in real-time. No need to refresh. ### Filtering Filter requests by: - **Direction** - Incoming (to your server) or outgoing (to external APIs) - **Method** - GET, POST, PUT, PATCH, DELETE - **Status** - 2xx, 3xx, 4xx, 5xx - **Errors** - Show only failed requests - **Slow** - Show only slow requests ### Search Search requests by URL or body content. ### Request Details Click any request to see: - Full URL - Timestamp - Duration - Request/response sizes - Request body (if enabled) - Response body (if enabled) - Error message (if any) ### cURL Export Copy any request as a cURL command for easy debugging and replay. ## Configuration ```javascript import { serve } from 'snapwyr/dashboard'; serve(3333, { host: 'localhost', // Bind address (default: 'localhost') open: true, // Auto-open browser (default: false) maxRequests: 1000, // Max requests to store (default: 1000) }); ``` ## API ### serve(port, options?) Start the dashboard server. ```javascript import { serve } from 'snapwyr/dashboard'; serve(3333); ``` ### stop() Stop the dashboard server. ```javascript import { stop } from 'snapwyr/dashboard'; stop(); ``` ### pushRequest(entry) Manually push a request to the dashboard. ```javascript import { pushRequest } from 'snapwyr/dashboard'; pushRequest({ id: 'unique-id', timestamp: new Date().toISOString(), method: 'GET', url: '/api/users', status: 200, duration: 45, slow: false, direction: 'incoming', }); ``` ## Incoming vs Outgoing The dashboard shows both types of requests: - **Incoming** (blue arrow) - Requests hitting your server via middleware - **Outgoing** (purple arrow) - Requests your app makes to external APIs ### Log Both ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; import { logRequests } from 'snapwyr'; import { serve } from 'snapwyr/dashboard'; const app = express(); // Log incoming requests (middleware) app.use(snapwyr({ logBody: true })); // Log outgoing requests (interceptors) logRequests({ logBody: true }); // To log axios requests, pass your axios instance import axios from 'axios'; logRequests({ axios: axios, // Required for axios interception logBody: true, }); // Dashboard shows both serve(3333); ``` ## Data Persistence The dashboard stores requests in memory. When your server restarts, data is cleared. This is intentional for a development tool: - No disk I/O overhead - No cleanup needed - Fresh state on each dev session - Privacy (nothing persisted to disk) ## Tips ### Use with nodemon The dashboard runs in the same process as your server. With nodemon, it restarts when files change. To reduce restarts, use nodemon's delay option: ```json { "watch": ["src"], "delay": "2000" } ``` ### External Logging Use the `transport` option to send logs to external services while keeping the dashboard: ```javascript snapwyr({ logBody: true, transport: (entry) => { // Send to external service fetch('https://logs.example.com', { method: 'POST', body: JSON.stringify(entry), }); }, }); ``` --- ## Framework Middleware URL: https://snapwyr.xyz/docs/guides/frameworks Description: Use Snapwyr middleware with Express, Next.js, Koa, Fastify, NestJS, and Hono ### Content # Framework Middleware Snapwyr provides middleware for popular Node.js frameworks to log incoming requests. ## Express ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; import { serve } from 'snapwyr/dashboard'; const app = express(); app.use( snapwyr({ logBody: true, requestId: true, redact: ['password', 'token'], }) ); serve(3333); // Dashboard at localhost:3333 app.get('/api/users', (req, res) => { res.json({ users: [] }); }); app.listen(3000); ``` ## Fastify ```javascript import Fastify from 'fastify'; import { snapwyr } from 'snapwyr/fastify'; import { serve } from 'snapwyr/dashboard'; const fastify = Fastify(); fastify.register(snapwyr, { logBody: true, requestId: true, }); serve(3333); fastify.get('/api/users', async () => { return { users: [] }; }); fastify.listen({ port: 3000 }); ``` ## Koa ```javascript import Koa from 'koa'; import { snapwyr } from 'snapwyr/koa'; import { serve } from 'snapwyr/dashboard'; const app = new Koa(); app.use( snapwyr({ logBody: true, requestId: true, }) ); serve(3333); app.use(async (ctx) => { ctx.body = { message: 'Hello' }; }); app.listen(3000); ``` ## Hono ```typescript import { Hono } from 'hono'; import { snapwyr } from 'snapwyr/hono'; import { serve } from 'snapwyr/dashboard'; const app = new Hono(); app.use( '*', snapwyr({ logBody: true, requestId: true, }) ); serve(3333); app.get('/api/users', (c) => c.json({ users: [] })); export default app; ``` ## NestJS ```typescript import { Module } from '@nestjs/common'; import { APP_INTERCEPTOR } from '@nestjs/core'; import { SnapwyrInterceptor } from 'snapwyr/nestjs'; @Module({ providers: [ { provide: APP_INTERCEPTOR, useValue: SnapwyrInterceptor({ logBody: true, requestId: true, }), }, ], }) export class AppModule {} ``` Start dashboard in `main.ts`: ```typescript import { serve } from 'snapwyr/dashboard'; async function bootstrap() { const app = await NestFactory.create(AppModule); serve(3333); await app.listen(3000); } bootstrap(); ``` ## Next.js Create `proxy.ts` in your project root (same level as `app` folder): ```typescript // proxy.ts import { snapwyr } from 'snapwyr/nextjs'; export const proxy = snapwyr({ logBody: true }); export const config = { matcher: '/api/:path*', }; ``` Note: The dashboard is designed for Node.js servers. In Next.js, use Express or Fastify for API routes if you need the dashboard. ```typescript // For dashboard support, use Express-based API routes import { snapwyr } from 'snapwyr/express'; import { serve } from 'snapwyr/dashboard'; ``` ## Configuration Options All middleware accepts these options: ```typescript { // Output format?: 'pretty' | 'json'; prefix?: string; silent?: boolean; // Body logBody?: boolean; bodySizeLimit?: number; // Filtering ignorePatterns?: (string | RegExp)[]; methods?: string[]; statusCodes?: number[]; errorsOnly?: boolean; // Features requestId?: boolean; sizeTracking?: boolean; slowThreshold?: number; redact?: (string | RegExp)[]; // Advanced transport?: (entry: LogEntry) => void; } ``` ## Full Example ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; import { logRequests } from 'snapwyr'; import { serve } from 'snapwyr/dashboard'; const app = express(); // Log incoming requests app.use( snapwyr({ logBody: true, requestId: true, sizeTracking: true, slowThreshold: 500, redact: ['password', 'token', 'apiKey'], ignorePatterns: ['/health', '/metrics'], }) ); // Log outgoing requests logRequests({ logBody: true, }); // To log axios requests, pass your axios instance import axios from 'axios'; logRequests({ axios: axios, // Required for axios interception logBody: true, }); // Start dashboard serve(3333); app.post('/api/login', (req, res) => { // Password is redacted in logs res.json({ token: 'xxx' }); }); app.get('/api/data', async (req, res) => { // This outgoing call is also logged const data = await fetch('https://api.example.com/data'); res.json(await data.json()); }); app.listen(3000); ``` Console output: ``` [m2x9k] POST 201 89ms 1.2KB /api/login [m2x9l] GET 200 234ms 4.5KB /api/data GET 200 180ms https://api.example.com/data ``` Dashboard shows both incoming and outgoing requests with direction indicators. --- ## API Reference URL: https://snapwyr.xyz/docs/reference/api Description: Complete API reference for Snapwyr ### Content # API Reference Complete reference for all Snapwyr APIs. ## Core SDK ### `logRequests(config?)` Start logging outgoing HTTP requests (fetch, axios). ```javascript import { logRequests } from 'snapwyr'; // Log fetch requests (automatic) logRequests(); // To log axios requests, pass your axios instance import axios from 'axios'; logRequests({ axios: axios, // Required for axios interception logBody: true, }); // Or with a custom axios instance const apiClient = axios.create({ baseURL: 'https://api.example.com' }); logRequests({ axios: apiClient, // Required for axios interception }); ``` ### `stopLogging()` Stop logging outgoing HTTP requests. ```javascript import { logRequests, stopLogging } from 'snapwyr'; logRequests(); // ... later stopLogging(); ``` ### `toCurl(params)` Generate a cURL command from request data. ```javascript import { toCurl } from 'snapwyr'; const curl = toCurl({ method: 'POST', url: 'https://api.example.com/users', headers: { 'Content-Type': 'application/json' }, body: '{"name":"John"}', }); ``` ### `generateRequestId()` Generate a unique request ID. ```javascript import { generateRequestId } from 'snapwyr'; const id = generateRequestId(); // "m2x9k-a3b7c" ``` ## Dashboard ### `serve(port, options?)` Start the dashboard server. ```javascript import { serve } from 'snapwyr/dashboard'; serve(3333); serve(3333, { host: 'localhost', open: true, maxRequests: 1000, }); ``` **Options:** - `host` - Bind address (default: `'localhost'`) - `open` - Auto-open browser (default: `false`) - `maxRequests` - Maximum requests to store (default: `1000`) ### `stop()` Stop the dashboard server. ```javascript import { stop } from 'snapwyr/dashboard'; stop(); ``` ### `pushRequest(entry)` Manually push a request to the dashboard. ```javascript import { pushRequest } from 'snapwyr/dashboard'; pushRequest({ id: 'unique-id', timestamp: new Date().toISOString(), method: 'GET', url: '/api/users', status: 200, duration: 45, slow: false, direction: 'incoming', }); ``` ## Types ### `SnapWyrConfig` Configuration interface for Snapwyr. ```typescript interface SnapWyrConfig { // Output format?: 'pretty' | 'json'; emoji?: boolean; silent?: boolean; prefix?: string; showTimestamp?: boolean; // Body logging logBody?: boolean; bodySizeLimit?: number; // Filtering errorsOnly?: boolean; methods?: string[]; statusCodes?: number[]; ignorePatterns?: (string | RegExp)[]; // Features slowThreshold?: number; requestId?: boolean; sizeTracking?: boolean; redact?: (string | RegExp)[]; // Advanced transport?: (entry: LogEntry) => void; enabled?: boolean; } ``` ### `LogEntry` Log entry passed to transport function and dashboard. ```typescript interface LogEntry { id: string; timestamp: string; method: string; url: string; status: number | undefined; duration: number; slow: boolean; error?: string; requestBody?: string; responseBody?: string; prefix?: string; requestSize?: number; responseSize?: number; totalSize?: number; direction?: 'incoming' | 'outgoing'; } ``` ### `RequestEvent` Event emitted when an HTTP request completes. ```typescript interface RequestEvent { id: string; method: string; url: string; status?: number; duration: number; timestamp: number; requestBody?: string; responseBody?: string; error?: string; headers?: Record; requestSize?: number; responseSize?: number; direction?: 'incoming' | 'outgoing'; } ``` ## Framework Middleware All middleware accepts `SnapWyrConfig` options. ### Express ```javascript import express from 'express'; import { snapwyr } from 'snapwyr/express'; const app = express(); app.use(snapwyr({ logBody: true })); ``` ### Fastify ```javascript import Fastify from 'fastify'; import { snapwyr } from 'snapwyr/fastify'; const fastify = Fastify(); fastify.register(snapwyr, { logBody: true }); ``` ### Koa ```javascript import Koa from 'koa'; import { snapwyr } from 'snapwyr/koa'; const app = new Koa(); app.use(snapwyr({ logBody: true })); ``` ### Hono ```typescript import { Hono } from 'hono'; import { snapwyr } from 'snapwyr/hono'; const app = new Hono(); app.use('*', snapwyr({ logBody: true })); ``` ### NestJS ```typescript import { Module } from '@nestjs/common'; import { APP_INTERCEPTOR } from '@nestjs/core'; import { SnapwyrInterceptor } from 'snapwyr/nestjs'; @Module({ providers: [ { provide: APP_INTERCEPTOR, useValue: SnapwyrInterceptor({ logBody: true }), }, ], }) export class AppModule {} ``` ### Next.js ```typescript // proxy.ts import { snapwyr } from 'snapwyr/nextjs'; export const proxy = snapwyr({ logBody: true }); export const config = { matcher: '/api/:path*', }; ``` ## Console Output ### Pretty Format (default) ``` 12:34:56 GET 200 45ms /api/users 12:34:57 POST 201 89ms /api/users 12:34:58 GET 404 12ms /api/unknown ``` ### JSON Format ```json { "id": "m2x9k", "timestamp": "2024-01-15T12:34:56.789Z", "method": "GET", "url": "/api/users", "status": 200, "duration": 45 } ``` ### Color Coding - **Method:** GET (blue), POST (green), PUT (yellow), PATCH (magenta), DELETE (red) - **Status:** 2xx (green), 3xx (cyan), 4xx (yellow), 5xx (red) - **Duration:** fast (green), medium (yellow), slow (red) ## Production Behavior All functions automatically disable when `NODE_ENV === 'production'`: - `logRequests()` does nothing - Middleware does nothing - Zero performance overhead To enable in production: ```javascript snapwyr({ enabled: true }); ``` ## Supported HTTP Clients `logRequests()` automatically intercepts: - `globalThis.fetch` (Node.js 18+) - Automatic, no configuration needed - `axios` - Requires passing your axios instance in the config **Example:** ```javascript import { logRequests } from 'snapwyr'; import axios from 'axios'; // Fetch is logged automatically logRequests(); await fetch('https://api.example.com/users'); // Axios requires passing the instance logRequests({ axios: axios }); await axios.get('https://api.example.com/users'); // Custom axios instances also work const apiClient = axios.create({ baseURL: 'https://api.example.com' }); logRequests({ axios: apiClient }); await apiClient.get('/users'); ``` ---