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

error-explorer-node-reporter

v1.1.2

Published

Node.js SDK for Error Explorer - Capture and report errors automatically

Downloads

3

Readme

@error-explorer/node

Node.js SDK for Error Explorer - Capture and report errors automatically from your Node.js applications.

✨ What's New in v1.1.0

  • 🚀 Non-blocking Initialization: SDK no longer blocks app startup with synchronous Git operations
  • 🛡️ Custom Error Handling: Configurable onError and onWarning callbacks for better integration
  • ⚡ Performance Features: Built-in offline queue, rate limiting, and circuit breaker
  • 🔧 Better TypeScript Support: Enhanced type definitions and improved developer experience
  • 📊 Health Monitoring: New methods to monitor SDK performance and status

Migration from v1.0.x

No breaking changes! All existing code continues to work. New features are opt-in:

// v1.0.x - still works
ErrorExplorer.init({
  webhookUrl: 'https://error-explorer.com',
  projectName: 'my-app'
});

// v1.1.0 - enhanced with custom error handling
ErrorExplorer.init({
  webhookUrl: 'https://error-explorer.com',
  projectName: 'my-app',
  onError: (error, context) => myLogger.error('ErrorExplorer failed:', error),
  onWarning: (message, context) => myLogger.warn('ErrorExplorer:', message)
});

Installation

npm install @error-explorer/node
# or
yarn add @error-explorer/node

Quick Start

Basic Setup

const { ErrorExplorer } = require('@error-explorer/node');

ErrorExplorer.init({
  webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL,
  projectName: process.env.ERROR_EXPLORER_PROJECT_NAME || 'my-node-app',
  environment: process.env.NODE_ENV || 'development',
});

// Capture uncaught exceptions and unhandled rejections
process.on('uncaughtException', ErrorExplorer.captureException);
process.on('unhandledRejection', ErrorExplorer.captureException);

Express.js Integration

const express = require('express');
const { ErrorExplorer } = require('@error-explorer/node');

const app = express();

// Initialize ErrorExplorer (two ways available)
ErrorExplorer.init({
  webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL,
  projectName: 'my-express-app',
  environment: process.env.NODE_ENV,
});

// Alternative: using configure() method (alias for init())
// ErrorExplorer.configure({
//   webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL,
//   projectName: 'my-express-app',
//   environment: process.env.NODE_ENV,
// });

// Setup automatic Express integration
ErrorExplorer.setupExpress(app, {
  captureRequestBody: true,
  captureRequestHeaders: true,
  skipHealthChecks: true,
  skipPaths: ['/favicon.ico']
});

// Your routes here
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// Error route for testing
app.get('/error/test', (req, res) => {
  throw new Error('Test error from Node Express');
});

// Start server
app.listen(3000);

Manual Error Capturing

try {
  // Your code here
  riskyOperation();
} catch (error) {
  // Capture the exception with context
  ErrorExplorer.captureException(error, {
    userId: req.user?.id,
    action: 'riskyOperation',
    additionalData: { some: 'data' }
  });
}

// Capture custom messages
ErrorExplorer.captureMessage('Something went wrong', 'error', {
  context: 'custom operation'
});

Configuration

Required Options

  • webhookUrl: Your Error Explorer webhook URL
  • projectName: Name of your project

Optional Options

ErrorExplorer.init({
  webhookUrl: 'https://your-domain.com/webhook/project-token',
  projectName: 'my-node-app',
  environment: 'production',        // Default: 'production'
  enabled: true,                    // Default: true
  userId: 'user123',               // Optional: Default user ID
  userEmail: '[email protected]',   // Optional: Default user email
  maxBreadcrumbs: 50,              // Default: 50
  timeout: 5000,                   // Default: 5000ms
  retries: 3,                      // Default: 3
  
  // Custom error handling callbacks
  onError: (error, context) => {   // Optional: Custom error handling
    console.error('ErrorExplorer failed:', error.message, context);
  },
  onWarning: (message, context) => { // Optional: Custom warning handling
    console.warn('ErrorExplorer warning:', message, context);
  },
  
  beforeSend: (data) => {          // Optional: Filter/modify data before sending
    // Filter sensitive data
    if (data.context?.password) {
      data.context.password = '[FILTERED]';
    }
    return data;
  },

  // Advanced options
  enableOfflineQueue: true,        // Default: true - Queue errors when offline
  maxQueueSize: 100,              // Default: 100 - Max queued errors
  enableRateLimit: true,          // Default: true - Rate limit requests
  maxRequestsPerMinute: 60,       // Default: 60 - Max requests per minute
  enableCircuitBreaker: true,     // Default: true - Circuit breaker pattern
  circuitBreakerThreshold: 5,     // Default: 5 - Failures before opening circuit
  circuitBreakerTimeout: 30000,   // Default: 30s - Circuit breaker timeout
});

Advanced Error Handling

Custom Error and Warning Callbacks

By default, ErrorExplorer logs errors and warnings to the console. You can customize this behavior to integrate with your existing logging infrastructure:

ErrorExplorer.init({
  webhookUrl: 'https://your-domain.com/webhook/project-token',
  projectName: 'my-app',
  
  // Custom error handling - called when ErrorExplorer itself fails
  onError: (error, context) => {
    // Log to your custom logger
    myLogger.error('ErrorExplorer internal error:', {
      error: error.message,
      stack: error.stack,
      context
    });
    
    // Send to alerting system
    alertManager.sendAlert('ErrorExplorer Failure', error);
  },
  
  // Custom warning handling - called for non-critical issues
  onWarning: (message, context) => {
    // Log to your custom logger
    myLogger.warn('ErrorExplorer warning:', { message, context });
    
    // Increment metrics
    metrics.increment('error_explorer.warnings', {
      message
    });
  }
});

Environment-Specific Configuration

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

ErrorExplorer.init({
  webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL,
  projectName: 'my-app',
  environment: process.env.NODE_ENV,
  
  onError: isProduction 
    ? (error, context) => {
        // Production: Send to PagerDuty
        pagerDuty.trigger('ErrorExplorer failure', error);
      }
    : (error, context) => {
        // Development: Detailed console logs
        console.error('ErrorExplorer error:', error, context);
      },
      
  onWarning: isProduction
    ? (message, context) => {
        // Production: Log to structured logger
        logger.warn('ErrorExplorer warning', { message, context });
      }
    : (message, context) => {
        // Development: Simple console warning
        console.warn(`ErrorExplorer: ${message}`, context);
      }
});

Integration with Popular Loggers

Winston Integration

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

ErrorExplorer.init({
  webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL,
  projectName: 'my-app',
  onError: (error, context) => {
    logger.error('ErrorExplorer failure', { 
      error: error.message, 
      context 
    });
  },
  onWarning: (message, context) => {
    logger.warn('ErrorExplorer warning', { 
      message, 
      context 
    });
  }
});

Pino Integration

const pino = require('pino');
const logger = pino();

ErrorExplorer.init({
  webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL,
  projectName: 'my-app',
  onError: (error, context) => {
    logger.error({ err: error, context }, 'ErrorExplorer failure');
  },
  onWarning: (message, context) => {
    logger.warn({ context }, 'ErrorExplorer warning: %s', message);
  }
});

Express.js Options

ErrorExplorer.setupExpress(app, {
  captureRequestBody: true,        // Default: false
  captureRequestHeaders: true,     // Default: false
  skipHealthChecks: true,          // Default: false
  skipPaths: ['/admin', '/api/health'] // Default: []
});

API Reference

ErrorExplorer.init(config)

Initializes the Error Explorer SDK.

ErrorExplorer.configure(config)

Alias for ErrorExplorer.init(config). Both methods work identically.

ErrorExplorer.captureException(error, context?)

Captures an exception with optional context.

ErrorExplorer.captureException(new Error('Something went wrong'), {
  userId: 123,
  action: 'checkout'
});

ErrorExplorer.captureMessage(message, level?, context?)

Captures a custom message.

ErrorExplorer.captureMessage('User logged in', 'info', {
  userId: 123
});

ErrorExplorer.addBreadcrumb(message, category?, level?, data?)

Adds a breadcrumb for debugging context.

ErrorExplorer.addBreadcrumb('User clicked button', 'ui', 'info', {
  buttonId: 'submit-btn'
});

ErrorExplorer.setUser(user)

Sets user context for all future error reports.

ErrorExplorer.setUser({
  id: 123,
  email: '[email protected]',
  username: 'john_doe'
});

ErrorExplorer.setupExpress(app, options?)

Sets up automatic Express.js integration.

Performance & Resilience Features

Offline Queue

ErrorExplorer automatically queues errors when the service is unreachable and retries them later:

ErrorExplorer.init({
  webhookUrl: 'https://your-domain.com/webhook/project-token',
  projectName: 'my-app',
  enableOfflineQueue: true,        // Default: true
  maxQueueSize: 100,              // Default: 100
  retries: 3,                     // Default: 3
});

Rate Limiting

Prevents overwhelming the Error Explorer service with too many requests:

ErrorExplorer.init({
  webhookUrl: 'https://your-domain.com/webhook/project-token',
  projectName: 'my-app',
  enableRateLimit: true,          // Default: true
  maxRequestsPerMinute: 60,       // Default: 60
});

Circuit Breaker

Automatically stops sending requests when the service is consistently failing:

ErrorExplorer.init({
  webhookUrl: 'https://your-domain.com/webhook/project-token',
  projectName: 'my-app',
  enableCircuitBreaker: true,     // Default: true
  circuitBreakerThreshold: 5,     // Default: 5 failures before opening
  circuitBreakerTimeout: 30000,   // Default: 30s timeout
});

Non-blocking Initialization

The SDK initializes asynchronously and won't block your application startup:

// ✅ Non-blocking - won't delay your app startup
ErrorExplorer.init({
  webhookUrl: 'https://your-domain.com/webhook/project-token',
  projectName: 'my-app',
});

// Your app starts immediately, even if git operations take time
app.listen(3000, () => {
  console.log('Server started!'); // This won't be delayed
});

Monitoring SDK Health

const errorReporter = ErrorExplorer.init({
  webhookUrl: 'https://your-domain.com/webhook/project-token',
  projectName: 'my-app',
});

// Check queue size
console.log('Queued errors:', errorReporter.getQueueSize());

// Check circuit breaker state
console.log('Circuit breaker:', errorReporter.getCircuitBreakerState());

// Check rate limit status
const rateLimitInfo = errorReporter.getRateLimitInfo();
console.log('Rate limit remaining:', rateLimitInfo.remaining);

// Manually flush queued errors
await errorReporter.flushQueue();

// Clear queue (useful for testing)
errorReporter.clearQueue();

// Cleanup resources
errorReporter.destroy();

Environment Variables

You can use environment variables for configuration:

ERROR_EXPLORER_WEBHOOK_URL=https://your-domain.com/webhook/project-token
ERROR_EXPLORER_PROJECT_NAME=my-node-app
NODE_ENV=production

TypeScript Support

This package includes comprehensive TypeScript definitions with full IntelliSense support.

import ErrorExplorer, { ErrorExplorerConfig } from '@error-explorer/node';

const config: ErrorExplorerConfig = {
  webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL!,
  projectName: 'my-typescript-app',
  environment: process.env.NODE_ENV,
  
  // TypeScript provides full autocomplete and type checking
  onError: (error: Error, context?: Record<string, any>) => {
    console.error('ErrorExplorer failed:', error.message, context);
  },
  
  onWarning: (message: string, context?: Record<string, any>) => {
    console.warn('ErrorExplorer warning:', message, context);
  }
};

const errorReporter = ErrorExplorer.init(config);

// All methods are fully typed
await errorReporter.captureException(new Error('Test'), { userId: 123 });
errorReporter.setUser({ id: 123, email: '[email protected]' });
errorReporter.addBreadcrumb('User action', 'ui', 'info', { buttonId: 'submit' });

// Health monitoring methods are typed too
const queueSize: number = errorReporter.getQueueSize();
const circuitState: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = errorReporter.getCircuitBreakerState();
const rateLimitInfo: { remaining: number; resetTime: number } = errorReporter.getRateLimitInfo();

Examples

Production-Ready Express Setup

const express = require('express');
const ErrorExplorer = require('@error-explorer/node');
const winston = require('winston');

const app = express();

// Setup structured logging
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.Console()
  ]
});

// Initialize ErrorExplorer with production configuration
const errorReporter = ErrorExplorer.init({
  webhookUrl: process.env.ERROR_EXPLORER_WEBHOOK_URL,
  projectName: 'my-production-app',
  environment: process.env.NODE_ENV,
  
  // Custom error handling integrated with logging infrastructure
  onError: (error, context) => {
    logger.error('ErrorExplorer SDK failure', {
      error: error.message,
      stack: error.stack,
      context,
      service: 'error-explorer-sdk'
    });
    
    // Send to alerting system in production
    if (process.env.NODE_ENV === 'production') {
      // alertManager.critical('ErrorExplorer SDK down', error);
    }
  },
  
  onWarning: (message, context) => {
    logger.warn('ErrorExplorer SDK warning', {
      message,
      context,
      service: 'error-explorer-sdk'
    });
  },
  
  // Performance tuning for high-traffic apps
  maxRequestsPerMinute: 120,
  maxQueueSize: 200,
  circuitBreakerThreshold: 10
});

// Middleware to set user context
app.use((req, res, next) => {
  if (req.user) {
    ErrorExplorer.setUser({
      id: req.user.id,
      email: req.user.email,
      role: req.user.role
    });
  }
  next();
});

// Setup Express integration with custom options
ErrorExplorer.setupExpress(app, {
  captureRequestBody: true,
  captureRequestHeaders: true,
  skipHealthChecks: true,
  skipPaths: ['/favicon.ico', '/metrics', '/health']
});

// Health check endpoint that includes ErrorExplorer status
app.get('/health', (req, res) => {
  const health = {
    status: 'healthy',
    timestamp: new Date().toISOString(),
    errorExplorer: {
      queueSize: errorReporter.getQueueSize(),
      circuitBreaker: errorReporter.getCircuitBreakerState(),
      rateLimit: errorReporter.getRateLimitInfo()
    }
  };
  
  res.json(health);
});

// Graceful shutdown
process.on('SIGTERM', () => {
  logger.info('SIGTERM received, shutting down gracefully');
  
  // Flush any queued errors before shutdown
  errorReporter.flushQueue()
    .then(() => {
      logger.info('ErrorExplorer queue flushed');
      errorReporter.destroy();
      process.exit(0);
    })
    .catch((error) => {
      logger.error('Failed to flush ErrorExplorer queue', error);
      errorReporter.destroy();
      process.exit(1);
    });
});

With Database Queries

const mysql = require('mysql2/promise');

async function getUserById(id) {
  try {
    ErrorExplorer.addBreadcrumb(`Fetching user ${id}`, 'database');
    
    const [rows] = await connection.execute('SELECT * FROM users WHERE id = ?', [id]);
    
    ErrorExplorer.addBreadcrumb(`Found ${rows.length} users`, 'database');
    
    return rows[0];
  } catch (error) {
    ErrorExplorer.captureException(error, {
      query: 'getUserById',
      userId: id
    });
    throw error;
  }
}

License

MIT