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

tetrabillboard-error-logger

v1.0.0

Published

Production-ready error logger for frontend applications with backend and AWS S3 support

Readme

@tetrabillboard/error-logger

Production-ready error logger for frontend applications with backend API and AWS S3 support.

Features

Automatic Error Capture

  • window.onerror - Global JavaScript errors
  • console.error - Console error messages
  • Unhandled Promise Rejections

Flexible Transport Options

  • Send to backend API endpoint
  • Upload directly to AWS S3 (presigned URL or credentials)
  • Support for both simultaneously

Smart Batching

  • Queue errors and send in batches
  • Configurable batch size and interval
  • Automatic flush on batch size threshold

Retry Logic

  • Exponential backoff for failed requests
  • Configurable retry attempts
  • Smart retry for 5xx and 429 errors

TypeScript Support

  • Full TypeScript definitions
  • Type-safe configuration
  • IntelliSense support

Production Ready

  • Zero dependencies
  • Lightweight (~5KB gzipped)
  • Framework agnostic
  • Browser environment detection

Installation

npm install @tetrabillboard/error-logger

Quick Start

Basic Usage (Backend Endpoint)

import { initErrorLogger } from '@tetrabillboard/error-logger';

initErrorLogger({
  endpoint: 'https://api.tetrabillboard.com/log-error',
  appName: 'cart-app',
  environment: 'production',
  release: 'v1.2.3'
});

With Batching

import { initErrorLogger } from '@tetrabillboard/error-logger';

initErrorLogger({
  endpoint: 'https://api.tetrabillboard.com/log-error',
  appName: 'cart-app',
  environment: 'production',
  release: 'v1.2.3',
  batch: true,
  batchSize: 10,
  batchInterval: 5000 // 5 seconds
});

With AWS S3 (Presigned URL)

import { initErrorLogger } from '@tetrabillboard/error-logger';

initErrorLogger({
  appName: 'cart-app',
  environment: 'production',
  s3: {
    presignedUrl: 'https://my-bucket.s3.amazonaws.com/...?X-Amz-Signature=...'
  }
});

With AWS S3 (Credentials)

import { initErrorLogger } from '@tetrabillboard/error-logger';

initErrorLogger({
  appName: 'cart-app',
  environment: 'production',
  s3: {
    bucket: 'my-error-logs',
    region: 'us-east-1',
    accessKeyId: 'YOUR_ACCESS_KEY',
    secretAccessKey: 'YOUR_SECRET_KEY',
    keyPrefix: 'error-logs/'
  }
});

Note: S3 upload with credentials requires implementing AWS SDK signing. For production, use presigned URLs or implement AWS SDK integration.

Dual Transport (Backend + S3)

import { initErrorLogger } from '@tetrabillboard/error-logger';

initErrorLogger({
  endpoint: 'https://api.tetrabillboard.com/log-error',
  appName: 'cart-app',
  environment: 'production',
  release: 'v1.2.3',
  s3: {
    presignedUrl: 'https://my-bucket.s3.amazonaws.com/...?X-Amz-Signature=...'
  }
});

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | endpoint | string | - | Backend API endpoint URL | | appName | string | Required | Application identifier | | environment | string | Required | Environment (production, staging, etc.) | | release | string | - | Release version | | batch | boolean | false | Enable error batching | | batchSize | number | 10 | Number of errors per batch | | batchInterval | number | 5000 | Batch flush interval (ms) | | debug | boolean | false | Enable debug logging | | s3 | S3Config | - | AWS S3 configuration | | headers | Record<string, string> | - | Custom HTTP headers | | maxRetries | number | 3 | Maximum retry attempts | | autoCaptureErrors | boolean | true | Auto-capture errors on init | | beforeSend | function | - | Filter/modify errors before sending |

API Reference

initErrorLogger(config)

Initialize the error logger with configuration.

import { initErrorLogger } from '@tetrabillboard/error-logger';

const logger = initErrorLogger({
  endpoint: 'https://api.example.com/errors',
  appName: 'my-app',
  environment: 'production'
});

logError(error, context?)

Manually log an error.

import { logError } from '@tetrabillboard/error-logger';

try {
  // Some code
} catch (error) {
  logError(error, { userId: '123', action: 'checkout' });
}

logMessage(message, level?, context?)

Log a message with severity level.

import { logMessage } from '@tetrabillboard/error-logger';

logMessage('Payment processing failed', 'error', { 
  orderId: '456',
  amount: 99.99 
});

flush()

Flush pending errors immediately.

import { flush } from '@tetrabillboard/error-logger';

// Before page unload
window.addEventListener('beforeunload', async () => {
  await flush();
});

destroyErrorLogger()

Remove error handlers and cleanup.

import { destroyErrorLogger } from '@tetrabillboard/error-logger';

destroyErrorLogger();

getErrorLogger()

Get the current logger instance.

import { getErrorLogger } from '@tetrabillboard/error-logger';

const logger = getErrorLogger();
if (logger) {
  logger.logError(new Error('Something went wrong'));
}

Advanced Usage

Custom Error Filtering

import { initErrorLogger } from '@tetrabillboard/error-logger';

initErrorLogger({
  endpoint: 'https://api.example.com/errors',
  appName: 'my-app',
  environment: 'production',
  beforeSend: (payload) => {
    // Ignore specific errors
    if (payload.message.includes('Script error')) {
      return false;
    }
    
    // Add custom fields
    payload.context = {
      ...payload.context,
      sessionId: getSessionId()
    };
    
    return payload;
  }
});

Custom Headers

import { initErrorLogger } from '@tetrabillboard/error-logger';

initErrorLogger({
  endpoint: 'https://api.example.com/errors',
  appName: 'my-app',
  environment: 'production',
  headers: {
    'Authorization': 'Bearer YOUR_TOKEN',
    'X-Custom-Header': 'value'
  }
});

React Integration

import React from 'react';
import { initErrorLogger, logError } from '@tetrabillboard/error-logger';

class ErrorBoundary extends React.Component {
  componentDidMount() {
    initErrorLogger({
      endpoint: 'https://api.example.com/errors',
      appName: 'react-app',
      environment: process.env.NODE_ENV,
      release: process.env.REACT_APP_VERSION
    });
  }

  componentDidCatch(error, errorInfo) {
    logError(error, { componentStack: errorInfo.componentStack });
  }

  render() {
    return this.props.children;
  }
}

Vue.js Integration

import { createApp } from 'vue';
import { initErrorLogger, logError } from '@tetrabillboard/error-logger';
import App from './App.vue';

const app = createApp(App);

initErrorLogger({
  endpoint: 'https://api.example.com/errors',
  appName: 'vue-app',
  environment: import.meta.env.MODE,
  release: import.meta.env.VITE_APP_VERSION
});

app.config.errorHandler = (err, vm, info) => {
  logError(err, { 
    component: vm?.$options.name,
    info 
  });
};

app.mount('#app');

Next.js Integration

// pages/_app.js
import { useEffect } from 'react';
import { initErrorLogger } from '@tetrabillboard/error-logger';

function MyApp({ Component, pageProps }) {
  useEffect(() => {
    initErrorLogger({
      endpoint: 'https://api.example.com/errors',
      appName: 'nextjs-app',
      environment: process.env.NODE_ENV,
      release: process.env.NEXT_PUBLIC_VERSION,
      batch: true
    });
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

Error Payload Structure

Errors are sent in the following format:

{
  message: string;           // Error message
  stack?: string;            // Stack trace
  type: string;              // Error type/name
  timestamp: string;         // ISO 8601 timestamp
  appName: string;           // Your app name
  environment: string;       // Environment
  release?: string;          // Release version
  url: string;               // Page URL
  userAgent: string;         // Browser user agent
  lineNumber?: number;       // Line number
  columnNumber?: number;     // Column number
  filename?: string;         // Source filename
  context?: object;          // Custom context
  level: 'error' | 'warning' | 'info';
}

Batch Format

When batching is enabled:

{
  "errors": [
    { /* error payload */ },
    { /* error payload */ }
  ]
}

Backend API Requirements

Your backend endpoint should:

  1. Accept POST requests
  2. Parse application/json content type
  3. Return appropriate HTTP status codes:
    • 200-299: Success
    • 429: Rate limit (will retry)
    • 500-599: Server error (will retry)

Example Express.js Handler

app.post('/log-error', express.json(), (req, res) => {
  const error = req.body;
  
  // Single error
  if (error.message) {
    console.error('Error received:', error);
    // Store in database, forward to monitoring service, etc.
  }
  
  // Batch errors
  if (error.errors && Array.isArray(error.errors)) {
    console.error('Batch errors received:', error.errors.length);
    error.errors.forEach(err => {
      // Process each error
    });
  }
  
  res.status(200).json({ success: true });
});

Browser Support

  • Chrome/Edge: Latest 2 versions
  • Firefox: Latest 2 versions
  • Safari: Latest 2 versions
  • iOS Safari: Latest 2 versions
  • Chrome Android: Latest version

Requires:

  • fetch API
  • Promise
  • WeakSet

TypeScript

The package includes TypeScript definitions out of the box.

import { 
  initErrorLogger, 
  ErrorLoggerConfig,
  ErrorPayload 
} from '@tetrabillboard/error-logger';

const config: ErrorLoggerConfig = {
  endpoint: 'https://api.example.com/errors',
  appName: 'my-app',
  environment: 'production',
  batch: true
};

initErrorLogger(config);

Development

# Install dependencies
npm install

# Build the package
npm run build

# Clean build artifacts
npm run clean

License

MIT © Tetrabillboard

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Support

For issues and questions, please open a GitHub issue at: https://github.com/tetrabillboard/error-logger/issues