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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lahin31/debugcontext-core

v0.1.2

Published

Zero-configuration debugging context SDK for Node.js — automatically captures request, runtime, system, git, and error context on every thrown error.

Readme

@lahin31/debugcontext-core

Zero-configuration debugging context SDK for Node.js.

When your application throws, DebugContext automatically captures everything you need to investigate the issue — request details, runtime state, system resources, Git metadata, and a full error trace — structured into one clean Incident object.

DebugContext is not an error tracking service (like Sentry) and not a logging library (like Winston). It generates structured debug context so you can ship it wherever you need — a file, a webhook, Slack, your own database.

npm version npm downloads License: MIT


Install

npm install @lahin31/debugcontext-core

For Express support, also install the adapter:

npm install @lahin31/debugcontext-core @lahin31/debugcontext-express

Quick Start

import DebugContext from '@lahin31/debugcontext-core';

// 1. Initialise once at startup
DebugContext.init();

// 2. Capture any error
try {
  throw new Error('database connection failed');
} catch (err) {
  const incident = DebugContext.capture(err);

  // Print to console
  DebugContext.toConsole(incident);

  // Get as JSON string
  console.log(DebugContext.toJSON(incident));

  // Write to NDJSON file
  DebugContext.toFile(incident, { path: 'logs/incidents.ndjson' });
}

Express Integration

import express from 'express';
import DebugContext from '@lahin31/debugcontext-core';
import DebugContextExpress from '@lahin31/debugcontext-express';

DebugContext.init();

const app = express();
app.use(express.json());

// Optional: mount before routes to enable route param capture
app.use(DebugContextExpress.requestMiddleware());

// Your routes
app.get('/users/:id', (req, res) => {
  throw new Error('User not found'); // captured automatically
});

// Mount error middleware LAST
app.use(DebugContextExpress.errorMiddleware());

app.listen(3000);

What an Incident looks like

{
  "incidentId": "3f2a1b4c-8e1d-4a2f-b3c9-1d2e3f4a5b6c",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "request": {
    "method": "GET",
    "url": "/users/42",
    "params": { "id": "42" },
    "query": {},
    "body": null,
    "headers": {
      "authorization": "[REDACTED]",
      "content-type": "application/json"
    },
    "ip": "127.0.0.1",
    "userAgent": "Mozilla/5.0 ..."
  },
  "runtime": {
    "timestamp": "2024-01-15T10:30:00.000Z",
    "environment": "production",
    "nodeVersion": "v20.11.0",
    "pid": 1234,
    "hostname": "prod-server-1",
    "uptimeSeconds": 3600.5,
    "workingDirectory": "/app"
  },
  "system": {
    "memory": {
      "rss": 52428800,
      "heapTotal": 30408704,
      "heapUsed": 18200000,
      "external": 1234,
      "arrayBuffers": 456
    },
    "heapUsagePercent": 59.8,
    "cpuLoadAvg": [0.5, 0.3, 0.2],
    "platform": "linux",
    "arch": "x64",
    "totalMemory": 8589934592,
    "freeMemory": 2147483648
  },
  "git": {
    "commitHash": "a1b2c3d4",
    "branch": "main",
    "packageVersion": "1.2.3"
  },
  "error": {
    "name": "Error",
    "message": "User not found",
    "stack": "Error: User not found\n    at ...",
    "cause": null
  }
}

API

DebugContext.init(options?)

Initialises the SDK. Call once at startup.

DebugContext.init({
  // Extra header names to redact
  sensitiveHeaders: ['x-my-secret-header'],

  // Extra body fields to redact
  sensitiveFields: ['myApiKey', 'internalToken'],

  // Hook called after every captured incident
  onIncident: async (incident) => {
    await fetch('https://my-backend.example.com/incidents', {
      method: 'POST',
      body: JSON.stringify(incident),
    });
  },

  // Attach global uncaughtException + unhandledRejection handlers
  // Default: true
  captureGlobalErrors: true,
});

DebugContext.capture(error, requestContext?)

Manually captures any error. Returns the Incident.

try {
  await riskyDatabaseCall();
} catch (err) {
  const incident = DebugContext.capture(err);
  DebugContext.toConsole(incident);
}

DebugContext.toConsole(incident?)

Prints a human-readable incident summary to console.error. Defaults to the last captured incident.

────────────────────────────────────────────────────────────
🐛  DebugContext Incident  3f2a1b4c-...
────────────────────────────────────────────────────────────

  Error      : Error: User not found
  Timestamp  : 2024-01-15T10:30:00.000Z
  Environment: production
  Node       : v20.11.0
  Commit     : a1b2c3d4 (main)
  Heap       : 59.8% used

  Request:
    GET /users/42
    IP        : 127.0.0.1
    User-Agent: curl/8.4.0

  Stack:
    Error: User not found
        at /app/routes/users.js:12:9

DebugContext.toJSON(incident?)

Returns the incident as a pretty-printed JSON string.

const json = DebugContext.toJSON();
fs.writeFileSync('incident.json', json ?? '');

DebugContext.toFile(incident?, options?)

Appends the incident as a single line to an NDJSON file. Creates the file and parent directories if they don't exist.

// Default path: incidents.ndjson in cwd
DebugContext.toFile(incident);

// Custom path
DebugContext.toFile(incident, { path: 'logs/incidents.ndjson' });

// Use with onIncident hook to log every error automatically
DebugContext.init({
  onIncident: (i) => DebugContext.toFile(i, { path: 'logs/incidents.ndjson' }),
});

DebugContext.middleware()

Returns a framework-agnostic capture function. Use this when building custom adapters.

const capture = DebugContext.middleware();
const incident = capture(error, requestContext);

Automatic Redaction

Sensitive values are always replaced with "[REDACTED]" before they appear in an Incident.

Headers (always redacted): authorization, cookie, set-cookie, x-api-key, x-auth-token, x-access-token, proxy-authorization, www-authenticate

Body fields (always redacted): password, secret, token, apikey, access_token, refresh_token, credit_card, cvv, ssn, private_key, and more.

Add extra names via init():

DebugContext.init({
  sensitiveHeaders: ['x-internal-token'],
  sensitiveFields: ['myCustomSecret'],
});

Tree-shakable named exports

import { init, capture, toJSON, toConsole, toFile, middleware } from '@lahin31/debugcontext-core';

// Individual collectors — compose your own pipeline
import { collectRuntime, collectSystem, collectGit, collectError } from '@lahin31/debugcontext-core';

// Redaction utilities — useful for custom adapters
import { redactHeaders, redactBody } from '@lahin31/debugcontext-core';

Design Principles

  • Zero config — works with a single DebugContext.init() call
  • No external dependencies — only Node.js built-ins (crypto, os, child_process, fs)
  • No cloud, no database — incidents are plain objects, send them anywhere
  • Tree-shakable — unused collectors are dropped by bundlers
  • Dual ESM/CJS — works in both import and require projects

Related Packages


License

MIT © lahin31