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

@scalable-labs/sentinel

v0.5.3

Published

Frontend error monitoring and tracking client with local storage, Microsoft Teams integration, and visual error viewer

Readme

@scalable-labs/sentinel

CI CodeQL npm version License: MIT Downloads

⚠️ Pre-1.0 Notice: This package is currently in active development and has not reached v1.0 yet. APIs may change and stability is not guaranteed. Use in production at your own risk. We welcome feedback and contributions!

Frontend error monitoring client for Sentinel by Scalable Labs. Automatically captures and reports failed API requests with support for local storage, Microsoft Teams integration, and visual error tracking.

🔗 Related Projects

Note: This repository (sentineljs) contains the source code for the npm package published as @scalable-labs/sentinel.

Installation

npm install @scalable-labs/sentinel

Quick Start

Local Mode with UI (No Backend Required)

Perfect for development or when you want to track errors locally without a backend:

import { createSentinel } from '@scalable-labs/sentinel';

const sentinel = createSentinel({
  mode: 'local',  // Store errors in browser IndexedDB
  showUI: true,   // Show floating error viewer button
  uiPosition: 'bottom-right',
  teamMapping: {
    '/api/users': 'platform',
    '/api/orders': 'commerce',
    '/api/products': 'catalog',
  },
  teamsChannelUrl: 'https://teams.microsoft.com/l/channel/...',
  captureHeaders: ['x-correlation-id', 'x-request-id'],
  getUserName: () => getCurrentUser()?.email,
});

// Errors are automatically captured and stored locally
// Click the ⚠️ button to view, copy, or send to Teams

Remote Mode (With Sentinel Backend)

import { createSentinel } from '@scalable-labs/sentinel';

const sentinel = createSentinel({
  mode: 'remote',
  backendUrl: 'https://sentinel.yourcompany.com',
  apiKey: 'your-api-key',
  enabled: process.env.NODE_ENV === 'production',
  teamMapping: {
    '/api/users': 'platform',
    '/api/orders': 'commerce',
  },
  getUserName: () => getCurrentUser()?.username,
});

// Fetch interceptor is automatically installed!
// All failed requests will be batched and sent to backend

Configuration

| Option | Type | Required | Default | Description | | ------------------ | ----------------------------- | --------------- | --------------- | ---------------------------------------------- | | mode | 'local' \| 'remote' | No | 'local' | Operating mode | | teamMapping | Record<string, string> | Yes | - | Map endpoints to teams | | enabled | boolean | No | true | Enable/disable reporting | | backendUrl | string | Yes (remote) | - | Sentinel backend URL (remote mode only) | | apiKey | string | Yes (remote) | - | API key for backend (remote mode only) | | showUI | boolean | No | false | Show visual error viewer (local mode only) | | uiPosition | 'bottom-right' \| ... | No | 'bottom-right'| Position of UI button | | teamsChannelUrl | string | No | - | Microsoft Teams channel URL for notifications | | captureHeaders | string[] | No | - | HTTP headers to capture from responses | | getUserName | () => string \| undefined | No | undefined | Function to get current username | | batchSize | number | No | 50 | Batch size (remote mode) | | batchInterval | number | No | 10000 | Batch interval in ms (remote mode) | | defaultTeam | string | No | 'unknown' | Team for unmapped endpoints | | dbName | string | No | 'sentinel' | IndexedDB database name (local mode) | | maxLocalErrors | number | No | 1000 | Max errors to store locally |

Features

🎯 Automatic Error Detection

Automatically captures failed HTTP requests (status >= 400) or network errors.

📦 Two Operating Modes

Local Mode:

  • Stores errors in browser IndexedDB
  • No backend required
  • Perfect for development
  • View errors in built-in UI
  • Export as JSON
  • Send to Microsoft Teams

Remote Mode:

  • Sends errors to Sentinel backend
  • Batched transmission
  • Prometheus metrics
  • Teams webhook alerts

🎨 Visual Error Viewer (Local Mode)

When showUI: true, a floating button (⚠️) appears to:

  • View all tracked errors grouped by team
  • Copy individual errors in JSON format
  • Copy all errors in JSON format
  • Send all errors to Microsoft Teams
  • Clear all tracked errors
  • Refresh error list

📊 Microsoft Teams Integration

Send errors directly to a Teams channel:

teamsChannelUrl: 'https://teams.microsoft.com/l/channel/19%3a...thread.tacv2/General?groupId=...&tenantId=...'

Errors are formatted as JSON with team tags for easy tracking. All errors are sent to the configured channel.

📋 Header Capture

Capture specific headers from HTTP responses for distributed tracing:

captureHeaders: ['x-correlation-id', 'x-request-id', 'x-trace-id']

Headers are included in error reports for debugging.

🏷️ Team Mapping

Map endpoints to teams using exact match, prefix matching, full URLs, or regex:

teamMapping: {
  // Path-based matching
  '/api/users': 'platform',                              // Exact: /api/users
  '/api/users/': 'platform',                             // Prefix: /api/users/123, /api/users/456
  '/api/orders': 'commerce',                             // Prefix: /api/orders/...

  // Full URL matching
  'https://api.example.com/users': 'platform',           // Exact hostname match
  'https://api.example.[tld]/users': 'platform',         // TLD variation: matches .com, .dk, .co.uk, etc.
  'https://payments.stripe.[tld]/': 'payments',          // TLD variation with path prefix

  // Regex patterns
  '/^\\/api\\/products\\/\\d+$/': 'catalog',             // Regex: /api/products/123
  '/^\\/api\\/payments/': 'payments',                    // Regex: starts with /api/payments
}

Matching Priority:

  1. Exact match - checked first
  2. Prefix/URL/Regex - checked in order (first match wins)
  3. Default team - if no match found

Pattern Types:

  • Path patterns: String starting with / (but not ending with / for regex)

    • Exact: /api/users matches only /api/users
    • Prefix: /api/users/ matches /api/users/123, /api/users/456/profile, etc.
  • Full URL patterns: String starting with http:// or https://

    • Exact hostname: https://api.example.com/users matches only api.example.com
    • TLD variation: https://api.example.[tld]/users matches:
      • https://api.example.com/users
      • https://api.example.dk/users
      • https://api.example.co.uk/users
    • Use [tld] placeholder in hostname to enable TLD variation
    • Path must match (prefix matching on path)
  • Regex patterns: String starting and ending with /

    • Pattern between slashes is used as the regex
    • Example: /^\\/api\\/v\\d+\\/users/ matches /api/v1/users, /api/v2/users, etc.
    • Invalid regex patterns are skipped with a warning

Combined Example:

teamMapping: {
  // Path patterns
  '/api/users': 'platform',                              // Exact match
  '/api/users/': 'platform',                             // Prefix match

  // Full URL patterns (exact hostname)
  'https://api.internal.com/data': 'backend',            // Internal API
  'https://payment-gateway.company.com/': 'payments',    // Payment service

  // Full URL patterns (with TLD variation)
  'https://api.example.[tld]/products': 'catalog',       // Multi-region product API
  'https://cdn.assets.[tld]/images': 'media',            // Multi-region CDN

  // Regex patterns for paths
  '/^\\/api\\/orders\\/\\d+$/': 'commerce',              // /api/orders/123
  '/^\\/api\\/v[12]\\/users/': 'platform',               // /api/v1/users, /api/v2/users

  // Regex patterns for full URLs
  '/^https:\\/\\/.*\\.stripe\\.com\\/.*$/': 'payments',  // Any Stripe subdomain
  '/^https:\\/\\/[a-z0-9-]+\\.cloudfront\\.net\\/.*$/': 'cdn', // CloudFront URLs
}

This configuration will match:

Path patterns:

  • /api/usersplatform (exact)
  • /api/users/123platform (prefix)

Full URL patterns (exact):

  • https://api.internal.com/databackend
  • https://payment-gateway.company.com/checkoutpayments

Full URL patterns (TLD variation):

  • https://api.example.com/productscatalog
  • https://api.example.dk/productscatalog
  • https://api.example.co.uk/products/itemcatalog
  • https://cdn.assets.com/images/logo.pngmedia
  • https://cdn.assets.fr/images/logo.pngmedia

Regex patterns (paths):

  • /api/orders/456commerce
  • /api/v1/usersplatform
  • /api/v2/users/searchplatform

Regex patterns (full URLs):

  • https://payments.stripe.com/v1/chargespayments
  • https://connect.stripe.com/oauthpayments
  • https://d1234567890.cloudfront.net/assets/app.jscdn

👤 Optional User Tracking

Track which users experience errors:

getUserName: () => {
  const user = localStorage.getItem('user');
  return user ? JSON.parse(user).username : undefined;
}

🔐 Environment-based Toggling

Enable/disable based on environment:

enabled: process.env.NODE_ENV === 'production'
// or
enabled: process.env.SENTINEL_ENABLED === 'true'

🛡️ Graceful Failure

If the Sentinel backend is unavailable, errors are logged to console but don't break your app.

Advanced Usage

Axios Integration

import axios from 'axios';
import { SentinelClient, installAxiosInterceptor } from '@scalable-labs/sentinel';

const sentinel = new SentinelClient({
  mode: 'remote',
  backendUrl: 'https://sentinel.yourcompany.com',
  apiKey: 'your-api-key',
  teamMapping: { '/api/users': 'platform' },
});

installAxiosInterceptor(axios, sentinel);

Manual Error Reporting

import { SentinelClient } from '@scalable-labs/sentinel';

const sentinel = new SentinelClient({
  mode: 'local',
  teamMapping: { '/api/users': 'platform' },
});

// Manually report an error with headers
try {
  const response = await fetch('/api/users/123');
  if (!response.ok) {
    const payload = await response.text();
    const headers = {
      'x-correlation-id': response.headers.get('x-correlation-id') || '',
    };
    sentinel.reportError('/api/users/123', 'GET', response.status, payload, headers);
  }
} catch (error) {
  sentinel.reportError('/api/users/123', 'GET', 0, 'Network error');
}

Export Local Errors

const sentinel = createSentinel({ mode: 'local', teamMapping: {...} });

// Get all errors as array
const errors = await sentinel.getLocalErrors();

// Export as JSON string
const json = await sentinel.exportLocalErrors();
console.log(json);

// Clear all errors
await sentinel.clearLocalErrors();

Manual Flush (Remote Mode)

Force send all queued errors immediately:

window.addEventListener('beforeunload', () => {
  sentinel.flush();
});

Examples

React App with Local Mode

// src/sentinel.ts
import { createSentinel } from '@scalable-labs/sentinel';

export const sentinel = createSentinel({
  mode: 'local',
  showUI: true,
  uiPosition: 'bottom-right',
  teamMapping: {
    '/api/auth': 'platform',
    '/api/users': 'platform',
    '/api/products': 'catalog',
  },
  teamsChannelUrl: 'https://teams.microsoft.com/l/channel/...',
  captureHeaders: ['x-correlation-id', 'x-request-id'],
  getUserName: () => {
    const userStr = localStorage.getItem('user');
    return userStr ? JSON.parse(userStr).email : undefined;
  },
});

// src/main.tsx
import { sentinel } from './sentinel';
// Sentinel is now monitoring all fetch requests!

Next.js App with Remote Mode

// lib/sentinel.ts
import { createSentinel } from '@scalable-labs/sentinel';

export const sentinel = createSentinel({
  mode: 'remote',
  backendUrl: process.env.NEXT_PUBLIC_SENTINEL_URL!,
  apiKey: process.env.NEXT_PUBLIC_SENTINEL_API_KEY!,
  enabled: process.env.NODE_ENV === 'production',
  teamMapping: {
    '/api/auth': 'platform',
    '/api/blog': 'content',
    '/api/products': 'ecommerce',
  },
  captureHeaders: ['x-trace-id'],
  getUserName: () => {
    if (typeof window !== 'undefined') {
      return sessionStorage.getItem('username') || undefined;
    }
  },
});

// app/layout.tsx or pages/_app.tsx
import { sentinel } from '@/lib/sentinel';
// Auto-monitoring enabled!

Development

# Install dependencies
npm install

# Build
npm run build

# Watch mode
npm run watch

# Run tests
npm test

# Lint
npm run lint

# Format
npm run format

Publishing

This package is published to npm as @scalable-labs/sentinel.

npm publish --access public

License

MIT

Contributing

Contributions welcome! Please open an issue or PR on GitHub.