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-angular-reporter

v2.0.1

Published

Advanced Angular SDK for Error Explorer - Comprehensive error tracking and monitoring with offline support, rate limiting, security validation, and real-time analytics

Downloads

27

Readme

error-explorer-angular

Advanced Angular SDK for Error Explorer - Comprehensive error tracking and monitoring with offline support, rate limiting, security validation, and real-time analytics.

✨ Features

  • 🚀 Advanced Error Tracking - Automatic capture of unhandled errors, HTTP failures, and performance issues
  • 🔄 Offline Support - Queue errors when offline, sync when back online
  • Rate Limiting - Smart deduplication and request throttling
  • 🔒 Security First - Built-in data sanitization and validation
  • 📊 Real-time Analytics - SDK health monitoring and performance metrics
  • 🧩 Angular Native - Deep Angular integration with route tracking and HTTP interceptors
  • 📱 Responsive Design - Works seamlessly across all devices and browsers
  • 🎯 Zero Config - Sensible defaults with extensive customization options

Installation

npm install error-explorer-angular
# ou
yarn add error-explorer-angular

Quick Start

Module Setup

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { ErrorExplorerModule } from 'error-explorer-angular';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    ErrorExplorerModule.forRoot({
      projectToken: 'your-project-token',
      apiUrl: 'https://error-explorer.com',
      projectName: 'my-angular-app',
      environment: 'production'
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Standalone Bootstrap (Angular 14+)

import { bootstrapApplication } from '@angular/platform-browser';
import { importProvidersFrom } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { ErrorExplorerModule } from 'error-explorer-angular';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [
    importProvidersFrom(
      HttpClientModule,
      ErrorExplorerModule.forRoot({
        webhookUrl: 'https://error-explorer.com/webhook/project-token',
        projectName: 'my-angular-app',
        environment: 'production'
      })
    )
  ]
});

Using in Components

import { Component } from '@angular/core';
import { ErrorExplorerService } from 'error-explorer-angular';

@Component({
  selector: 'app-example',
  template: `
    <button (click)="triggerError()">Trigger Error</button>
    <button (click)="captureMessage()">Capture Message</button>
  `
})
export class ExampleComponent {
  constructor(private errorExplorer: ErrorExplorerService) {
    // Set user context
    this.errorExplorer.setUser({
      id: 123,
      email: '[email protected]',
      username: 'john_doe'
    });
  }

  triggerError() {
    try {
      throw new Error('This is a test error');
    } catch (error) {
      this.errorExplorer.captureException(error as Error, {
        component: 'ExampleComponent',
        action: 'triggerError'
      });
    }
  }

  captureMessage() {
    this.errorExplorer.addBreadcrumb('User clicked capture message', 'user');
    this.errorExplorer.captureMessage('User performed an action', 'info', {
      action: 'captureMessage',
      component: 'ExampleComponent'
    });
  }
}

Configuration

Required Options

  • projectToken: Your Error Explorer project token
  • apiUrl: Your Error Explorer API URL
  • projectName: Name of your project

All Configuration Options

ErrorExplorerModule.forRoot({
  // Required
  projectToken: 'your-project-token',
  apiUrl: 'https://error-explorer.com',
  projectName: 'my-angular-app',
  
  // Basic settings
  environment: 'production',              // Default: 'production'
  enabled: true,                          // Default: true
  debug: false,                           // Default: false
  version: '1.0.0',                      // App version
  commitHash: 'abc123',                  // Git commit hash
  
  // User context
  userId: 'user123',                     // Default user ID
  userEmail: '[email protected]',         // Default user email
  customData: { plan: 'premium' },       // Custom metadata
  
  // Performance & Limits
  maxBreadcrumbs: 50,                    // Default: 50
  maxRequestsPerMinute: 10,              // Default: 10
  duplicateErrorWindow: 5000,            // Default: 5000ms
  
  // Retry configuration
  maxRetries: 3,                         // Default: 3
  initialRetryDelay: 1000,               // Default: 1000ms
  maxRetryDelay: 30000,                  // Default: 30000ms
  
  // Offline support
  enableOfflineSupport: true,            // Default: true
  maxOfflineQueueSize: 50,               // Default: 50
  offlineQueueMaxAge: 86400000,          // Default: 24h
  
  // Security & Network
  requestTimeout: 30000,                 // Default: 30000ms
  requireHttps: false,                   // Default: false
  allowedDomains: ['mydomain.com'],      // Optional: restrict domains
  
  // Angular specific
  captureRouteChanges: true,             // Default: true
  captureHttpErrors: true,               // Default: true
  
  // Data filtering
  beforeSend: (data) => {                // Optional: Filter/modify data
    // Filter sensitive data
    if (data.context?.password) {
      data.context.password = '[FILTERED]';
    }
    return data;
  }
})

### Providing the Commit Hash

To link errors with your source code, you should provide the git commit hash of the current build. You can do this by setting an environment variable during your build process.

**1. Get the commit hash and set it in your environment files:**

You can use a script to get the commit hash and write it to your environment file before building.

```bash
# In your package.json scripts
"scripts": {
  "prebuild": "node -e \"require('fs').writeFileSync('./src/environments/commit.ts', 'export const commit = { hash: \\"' + require('child_process').execSync('git rev-parse HEAD').toString().trim() + '\\" };')\"",
  "build": "npm run prebuild && ng build"
}

2. Import the commit hash and use it in your configuration:

// src/environments/commit.ts (will be generated by the script)
export const commit = { hash: "a1b2c3d..." };
// app.module.ts
import { commit } from '../environments/commit';

ErrorExplorerModule.forRoot({
  // ... other config
  commitHash: commit.hash,
})

Features

Automatic Error Handling

The module automatically captures:

  • Unhandled Exceptions: Global error handler catches all unhandled errors
  • HTTP Errors: Interceptor captures HTTP 4xx/5xx errors
  • Route Changes: Navigation events are tracked as breadcrumbs
  • Slow HTTP Requests: Requests taking longer than 5 seconds

Manual Error Capture

// Capture exceptions (new async API)
try {
  await riskyOperation();
} catch (error) {
  await this.errorExplorer.reportError(error as Error, {
    operation: 'riskyOperation',
    userId: this.currentUserId
  });
}

// Capture messages (enhanced)
await this.errorExplorer.reportMessage('User logged in', 'info', {
  userId: 123,
  timestamp: Date.now(),
  sessionId: 'abc123'
});

// Add breadcrumbs (improved)
this.errorExplorer.addBreadcrumb('User clicked submit', 'user', 'info', {
  formData: this.formValue,
  buttonId: 'submit-btn'
});

// User actions (new)
this.errorExplorer.logUserAction('form_submitted', {
  formType: 'contact',
  validationPassed: true
});

// Navigation tracking (enhanced)
this.errorExplorer.logNavigation('/home', '/profile', {
  trigger: 'menu_click'
});

HTTP Error Monitoring

HTTP errors are automatically captured and include:

// The interceptor captures:
// - Request method, URL, headers
// - Response status, headers
// - Request duration
// - Error details

// You can also manually capture HTTP errors
this.http.get('/api/data').subscribe({
  next: (data) => {
    // Success
  },
  error: (error: HttpErrorResponse) => {
    this.errorExplorer.captureHttpError(error, {
      customContext: 'additional data'
    });
  }
});

User Context Management

// Set user context globally
this.errorExplorer.setUser({
  id: 123,
  email: '[email protected]',
  username: 'john_doe',
  subscription: 'premium',
  customData: {
    preferences: {},
    permissions: []
  }
});

// User context is automatically included in all error reports

Breadcrumb Management

// Add custom breadcrumbs
this.errorExplorer.addBreadcrumb('User started checkout', 'user');
this.errorExplorer.addBreadcrumb('Payment method selected', 'user', 'info', {
  paymentMethod: 'credit_card'
});

// Access breadcrumb manager directly
const breadcrumbManager = this.errorExplorer.getBreadcrumbManager();
breadcrumbManager.addComponentLifecycle('MyComponent', 'ngOnInit');
breadcrumbManager.addUserInteraction('click', 'submit-button');

🚀 Advanced Features

Real-time Analytics & Monitoring

export class DashboardComponent {
  constructor(private errorExplorer: ErrorExplorerService) {}

  getSDKStats() {
    const stats = this.errorExplorer.getStats();
    console.log({
      queueSize: stats.queueSize,
      isOnline: stats.isOnline,
      rateLimitRemaining: stats.rateLimitRemaining,
      sdkMetrics: stats.sdkMetrics,
      quotaUsage: stats.quotaUsage,
      healthStatus: stats.healthStatus
    });
  }

  async flushOfflineQueue() {
    // Manually flush any queued errors
    await this.errorExplorer.flushQueue();
  }

  updateConfiguration() {
    // Dynamic configuration updates
    this.errorExplorer.updateConfig({
      debug: true,
      maxRequestsPerMinute: 20
    });
  }
}

Offline Support & Queue Management

// The SDK automatically handles offline scenarios
export class OfflineAwareComponent implements OnInit {
  constructor(private errorExplorer: ErrorExplorerService) {}

  ngOnInit() {
    // Errors reported while offline are automatically queued
    this.errorExplorer.reportError(new Error('Network issue'), {
      context: 'offline_scenario'
    });

    // When back online, queued errors are automatically sent
    window.addEventListener('online', async () => {
      await this.errorExplorer.flushQueue();
      console.log('Offline queue processed');
    });
  }
}

Rate Limiting & Security

// The SDK includes intelligent rate limiting and security features
export class SecurityExampleComponent {
  constructor(private errorExplorer: ErrorExplorerService) {}

  demonstrateRateLimiting() {
    // Duplicate errors within 5 seconds are automatically deduplicated
    for (let i = 0; i < 10; i++) {
      this.errorExplorer.reportError(new Error('Same error'));
    }
    // Only the first error will be sent, others are rate-limited

    // Rate limiting prevents spam
    for (let i = 0; i < 100; i++) {
      this.errorExplorer.reportError(new Error(`Error ${i}`));
    }
    // Only 10 requests per minute (default) are allowed
  }

  demonstrateDataSanitization() {
    // Sensitive data is automatically sanitized
    this.errorExplorer.reportError(new Error('Login failed'), {
      username: '[email protected]',
      password: 'secret123', // This will be filtered out
      apiKey: 'abc123'       // This will be filtered out
    });
  }
}

Quota Management

export class QuotaExampleComponent {
  constructor(private errorExplorer: ErrorExplorerService) {}

  checkQuotaUsage() {
    const stats = this.errorExplorer.getStats();
    const quotaUsage = stats.quotaUsage;

    console.log('Daily usage:', {
      used: quotaUsage.daily.used,
      limit: quotaUsage.daily.limit,
      remaining: quotaUsage.daily.limit - quotaUsage.daily.used
    });

    console.log('Monthly usage:', {
      used: quotaUsage.monthly.used,
      limit: quotaUsage.monthly.limit
    });

    console.log('Burst usage:', {
      used: quotaUsage.burst.used,
      limit: quotaUsage.burst.limit
    });
  }
}

Enhanced User Context Management

export class UserContextComponent {
  constructor(private errorExplorer: ErrorExplorerService) {}

  setDetailedUserContext() {
    // Enhanced user context with custom data
    this.errorExplorer.setUser({
      id: 'user-123',
      email: '[email protected]',
      username: 'john_doe',
      subscription: 'premium',
      role: 'admin',
      customData: {
        preferences: { theme: 'dark', language: 'en' },
        permissions: ['read', 'write', 'admin'],
        lastLogin: new Date().toISOString(),
        deviceInfo: {
          type: 'desktop',
          os: 'Windows 10',
          browser: 'Chrome'
        }
      }
    });

    // Individual setters
    this.errorExplorer.setUserId('user-456');
    this.errorExplorer.setUserEmail('[email protected]');
    this.errorExplorer.setCustomData({
      experiment: 'A',
      feature_flags: ['new_ui', 'beta_feature']
    });
  }
}

Advanced Usage

Custom Error Handler

import { ErrorHandler, Injectable } from '@angular/core';
import { ErrorExplorerService } from 'error-explorer-angular';

@Injectable()
export class CustomErrorHandler implements ErrorHandler {
  constructor(private errorExplorer: ErrorExplorerService) {}

  handleError(error: any): void {
    // Add custom logic
    console.error('Custom error handling:', error);
    
    // Capture with Error Explorer
    if (error instanceof Error) {
      this.errorExplorer.captureException(error, {
        handled_by: 'CustomErrorHandler',
        custom_data: 'additional context'
      });
    }
  }
}

// In your module
@NgModule({
  providers: [
    {
      provide: ErrorHandler,
      useClass: CustomErrorHandler
    }
  ]
})
export class AppModule { }

Performance Monitoring

@Component({
  // ...
})
export class PerformanceComponent implements OnInit, OnDestroy {
  private startTime = Date.now();

  constructor(private errorExplorer: ErrorExplorerService) {}

  ngOnInit() {
    this.errorExplorer.addBreadcrumb('Component initialized', 'angular.lifecycle');
  }

  ngOnDestroy() {
    const duration = Date.now() - this.startTime;
    
    if (duration > 5000) {
      this.errorExplorer.captureMessage(
        'Slow component lifecycle',
        'warning',
        {
          component: 'PerformanceComponent',
          duration,
          lifecycle: 'ngOnDestroy'
        }
      );
    }
  }

  onSlowOperation() {
    const start = Date.now();
    
    // Perform operation
    this.heavyComputation();
    
    const duration = Date.now() - start;
    this.errorExplorer.addBreadcrumb(
      `Heavy computation completed in ${duration}ms`,
      'performance',
      duration > 1000 ? 'warning' : 'info'
    );
  }
}

Environment-specific Configuration

// environment.ts
export const environment = {
  production: false,
  errorExplorer: {
    webhookUrl: 'http://localhost:8000/webhook/dev-token',
    projectName: 'my-app-dev',
    environment: 'development',
    enabled: true,
    captureConsoleErrors: true
  }
};

// environment.prod.ts
export const environment = {
  production: true,
  errorExplorer: {
    webhookUrl: 'https://error-explorer.com/webhook/prod-token',
    projectName: 'my-app',
    environment: 'production',
    enabled: true,
    captureConsoleErrors: false
  }
};

// app.module.ts
@NgModule({
  imports: [
    ErrorExplorerModule.forRoot(environment.errorExplorer)
  ]
})
export class AppModule { }

Route-specific Error Handling

import { Router, NavigationError } from '@angular/router';

@Component({
  // ...
})
export class AppComponent {
  constructor(
    private router: Router,
    private errorExplorer: ErrorExplorerService
  ) {
    // Handle navigation errors
    this.router.events.subscribe(event => {
      if (event instanceof NavigationError) {
        this.errorExplorer.captureException(
          new Error(`Navigation failed: ${event.error}`),
          {
            url: event.url,
            navigation_error: true
          }
        );
      }
    });
  }
}

📚 API Reference

ErrorExplorerService

Core Methods

  • reportError(error: Error, additionalData?: Record<string, any>): Promise<void> - Report an error (new async API)
  • reportMessage(message: string, level?: 'info' | 'warning' | 'error', additionalData?: Record<string, any>): Promise<void> - Report a message
  • addBreadcrumb(message: string, category?: string, level?: ErrorLevel, data?: Record<string, any>): void - Add breadcrumb
  • logUserAction(action: string, data?: Record<string, any>): void - Log user action
  • logNavigation(from: string, to: string, data?: Record<string, any>): void - Log navigation

User Context Methods

  • setUser(user: UserContext): void - Set complete user context
  • setUserId(userId: string): void - Set user ID
  • setUserEmail(email: string): void - Set user email
  • setCustomData(data: Record<string, any>): void - Set custom metadata

Utility Methods

  • clearBreadcrumbs(): void - Clear all breadcrumbs
  • isEnabled(): boolean - Check if SDK is enabled
  • getStats() - Get SDK statistics and health metrics
  • flushQueue(): Promise<void> - Flush offline queue
  • updateConfig(updates: Partial<ErrorExplorerConfig>): void - Update configuration
  • destroy(): void - Clean up SDK resources

Legacy Methods (Backward Compatible)

  • captureException(error: Error, context?: Record<string, any>): void - Capture an exception
  • captureMessage(message: string, level?: ErrorLevel, context?: Record<string, any>): void - Capture a message
  • captureHttpError(error: HttpErrorResponse, context?: Record<string, any>): void - Capture HTTP error
  • getBreadcrumbManager(): BreadcrumbManager - Get breadcrumb manager
  • getConfig() - Get current configuration

BreadcrumbManager

New Methods

  • logHttpRequest(method: string, url: string, status: number, data?: Record<string, any>): void - Log HTTP request
  • logNavigation(from: string, to: string, data?: Record<string, any>): void - Log navigation
  • logUserAction(action: string, data?: Record<string, any>): void - Log user action
  • logConsole(level: 'error' | 'warn' | 'info' | 'debug', message: string): void - Log console message
  • clearBreadcrumbs(): void - Clear all breadcrumbs

Legacy Methods

  • addHttpRequest(method: string, url: string, statusCode?: number, duration?: number): void
  • addNavigation(from: string, to: string): void
  • addUserInteraction(event: string, target: string, data?: Record<string, any>): void
  • addComponentLifecycle(componentName: string, lifecycle: string): void
  • addConsoleLog(level: string, message: string, data?: any): void
  • addCustom(message: string, data?: Record<string, any>): void

Statistics Interface

interface SDKStats {
  queueSize: number;
  isOnline: boolean;
  rateLimitRemaining: number;
  rateLimitReset: number;
  sdkMetrics: SDKMetrics;
  quotaUsage: QuotaUsage;
  healthStatus: HealthStatus;
}

interface SDKMetrics {
  errorsReported: number;
  errorsDropped: number;
  requestsSuccessful: number;
  requestsFailed: number;
  averageResponseTime: number;
  queueSize: number;
  bytesTransmitted: number;
}

interface HealthStatus {
  status: 'healthy' | 'degraded' | 'unhealthy';
  issues: string[];
  uptime: number;
}

🔄 Migration Guide (v1 to v2)

Breaking Changes

  1. Configuration Format - webhookUrl replaced with projectToken + apiUrl
  2. New Async API - reportError() and reportMessage() are now async
  3. Enhanced Types - More comprehensive TypeScript interfaces

Configuration Migration

// v1 Configuration
ErrorExplorerModule.forRoot({
  webhookUrl: 'https://error-explorer.com/webhook/project-token',
  projectName: 'my-app'
})

// v2 Configuration  
ErrorExplorerModule.forRoot({
  projectToken: 'project-token',
  apiUrl: 'https://error-explorer.com',
  projectName: 'my-app'
})

API Migration

// v1 - Synchronous
this.errorExplorer.captureException(error);

// v2 - Asynchronous (recommended)
await this.errorExplorer.reportError(error);

// Legacy API still works for backward compatibility
this.errorExplorer.captureException(error); // Still supported

New Features Available

  • ✅ Offline error queuing
  • ✅ Intelligent rate limiting
  • ✅ Security validation
  • ✅ Real-time SDK monitoring
  • ✅ Enhanced breadcrumbs
  • ✅ Quota management
  • ✅ Performance metrics

🛠️ Development

Building the SDK

npm install
npm run build

Running Tests

npm test
npm run test:coverage

Type Checking

npm run typecheck

TypeScript Support

Full TypeScript support with comprehensive type definitions included.

Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+
  • Modern mobile browsers

🤝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

MIT License - see the LICENSE file for details.

🆘 Support