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

@firebreak/vitals

v3.0.1

Published

Deep healthcheck endpoints following the HEALTHCHECK_SPEC format

Downloads

1,524

Readme

Vitals (Node.js)

Structured healthcheck endpoints for Node.js services. Register health checks, run them concurrently with timeouts, and expose them via Express or Next.js. Health checks always run — a configurable detail policy controls whether callers see a summary status or full diagnostic results.

Install

npm install @firebreak/vitals

Peer dependencies are optional — install only what you need:

npm install pg        # for PostgreSQL checks
npm install ioredis   # for Redis checks
npm install express   # for Express integration

Quick Start (Express)

import { HealthcheckRegistry, extractToken, verifyToken } from '@firebreak/vitals';
import { createHealthcheckMiddleware } from '@firebreak/vitals/express';
import { pgPoolCheck } from '@firebreak/vitals/checks/postgres';
import { ioredisClientCheck } from '@firebreak/vitals/checks/redis';
import { httpCheck } from '@firebreak/vitals/checks/http';
import express from 'express';

const registry = new HealthcheckRegistry({ defaultTimeout: 5000 });

registry.add('postgres', pgPoolCheck(pool));
registry.add('redis', ioredisClientCheck(redisClient));
registry.add('api', httpCheck('https://api.example.com/health'));

const app = express();
app.get('/vitals', createHealthcheckMiddleware({
  registry,
  resolveDetail: (req) => {
    const token = extractToken({
      queryParams: req.queryParams as Record<string, string>,
      authorizationHeader: req.authorizationHeader as string | null,
    });
    if (token && verifyToken(token, process.env.VITALS_TOKEN!)) return 'full';
    return 'summary';
  },
  metadata: {
    build: process.env.BUILD_SHA,
    buildTimestamp: process.env.BUILD_TIMESTAMP,
  },
}));

Hit /vitals without a valid token to get a summary response with real health status:

{ "status": "healthy", "timestamp": "...", "build": "stg-45d76e5", "buildTimestamp": "2025-02-25T19:41:56Z" }

When resolveDetail returns 'full', the full response with check results is returned.

Quick Start (Next.js)

// app/vitals/route.ts
import { HealthcheckRegistry, extractToken, verifyToken } from '@firebreak/vitals';
import { createNextHandler } from '@firebreak/vitals/next';
import { pgClientCheck } from '@firebreak/vitals/checks/postgres';
import { httpCheck } from '@firebreak/vitals/checks/http';

const registry = new HealthcheckRegistry({ defaultTimeout: 5000 });

if (process.env.DATABASE_URL) {
  registry.add('postgres', pgClientCheck(process.env.DATABASE_URL));
}
registry.add('api', httpCheck(`${process.env.API_BASE_URL}/health`));

export const GET = createNextHandler({
  registry,
  resolveDetail: (req) => {
    const token = extractToken({
      queryParams: req.queryParams as Record<string, string>,
      authorizationHeader: req.authorizationHeader as string | null,
    });
    if (token && verifyToken(token, process.env.VITALS_TOKEN!)) return 'full';
    return 'summary';
  },
  metadata: {
    build: process.env.BUILD_SHA,
  },
});

API

HealthcheckRegistry

const registry = new HealthcheckRegistry({ defaultTimeout: 5000 });

registry.add(name, checkFn, options?)

Register a named async check function. Options: { timeout?: number }.

registry.add('service', async () => ({
  status: Status.HEALTHY,
  message: '',
}), { timeout: 3000 });

Check functions return a CheckInput with status and message. The latencyMs field is optional — the registry measures wall-clock latency automatically using performance.now().

registry.check(name, checkFn?, options?)

Decorator-style registration. Can be used as a method decorator or called directly.

registry.run()

Execute all registered checks concurrently. Returns a HealthcheckResponse with the worst overall status and registry-measured latency for each check.

const response = await registry.run();
// { status: 2, timestamp: '...', checks: { service: { status: 2, latencyMs: 12, message: '' } } }

const json = toJson(response);
// { status: 'healthy', timestamp: '...', checks: { ... } }

Status

import { Status, statusToLabel, statusFromString, httpStatusCode } from '@firebreak/vitals';

Status.HEALTHY  // 2
Status.DEGRADED // 1
Status.OUTAGE   // 0

statusToLabel(Status.HEALTHY) // 'healthy'
statusFromString('degraded')  // Status.DEGRADED
httpStatusCode(Status.HEALTHY) // 200
httpStatusCode(Status.OUTAGE)  // 503

Built-in Checks

HTTP

import { httpCheck } from '@firebreak/vitals/checks/http';

// Basic URL check — returns HEALTHY if response is 2xx
registry.add('api', httpCheck('https://api.example.com/health'));

// With options
registry.add('api', httpCheck('https://api.example.com/health', {
  method: 'HEAD',
  headers: { 'X-Api-Key': 'secret' },
  timeout: 3000, // default: 5000ms
}));

PostgreSQL

import { pgClientCheck, pgPoolCheck } from '@firebreak/vitals/checks/postgres';

// Fresh connection each time (good for validating connectivity)
registry.add('pg', pgClientCheck('postgresql://localhost:5432/mydb'));

// Existing pg.Pool (good for production — reuses connections)
registry.add('pg', pgPoolCheck(pool));

Redis

import { ioredisCheck, ioredisClientCheck } from '@firebreak/vitals/checks/redis';

// Fresh connection each time
registry.add('redis', ioredisCheck('redis://localhost:6379'));

// Existing ioredis client
registry.add('redis', ioredisClientCheck(client));

Custom Checks

Check functions only need to return status and message. The registry measures latency automatically:

registry.add('databricks', async () => {
  try {
    await databricksService.query('SELECT 1');
    return { status: Status.HEALTHY, message: '' };
  } catch (error) {
    return { status: Status.OUTAGE, message: error.message };
  }
});

Sync Checks

Wrap synchronous functions to use as health checks:

import { syncCheck, Status } from '@firebreak/vitals';

registry.add('disk', syncCheck(() => ({
  status: checkDiskSpace('/') > 1_000_000_000 ? Status.HEALTHY : Status.DEGRADED,
  message: '',
})));

Framework Integrations

Express

import { createHealthcheckMiddleware } from '@firebreak/vitals/express';

app.get('/vitals', createHealthcheckMiddleware({
  registry,
  resolveDetail: (req) => {    // optional — omit for always-summary
    const token = extractToken({
      queryParams: req.queryParams as Record<string, string>,
      authorizationHeader: req.authorizationHeader as string | null,
    });
    if (token && verifyToken(token, 'my-secret-token')) return 'full';
    return 'summary';
  },
  metadata: {                  // optional — included in summary & full responses
    build: 'stg-45d76e5',
  },
}));

Next.js (App Router)

import { createNextHandler } from '@firebreak/vitals/next';

export const GET = createNextHandler({
  registry,
  resolveDetail: (req) => {
    const token = extractToken({
      queryParams: req.queryParams as Record<string, string>,
      authorizationHeader: req.authorizationHeader as string | null,
    });
    if (token && verifyToken(token, process.env.VITALS_TOKEN!)) return 'full';
    return 'summary';
  },
  metadata: { build: process.env.BUILD_SHA },
});

Framework-Agnostic Handler

For other frameworks, use the generic handler directly:

import { createHealthcheckHandler, extractToken, verifyToken } from '@firebreak/vitals';

const handle = createHealthcheckHandler({
  registry,
  resolveDetail: (req) => {
    const token = extractToken({
      queryParams: req.queryParams as Record<string, string>,
      authorizationHeader: req.authorizationHeader as string | null,
    });
    if (token && verifyToken(token, process.env.VITALS_TOKEN!)) return 'full';
    return 'summary';
  },
  metadata: { build: 'stg-45d76e5' },
});

// resolveDetail returns 'summary' → summary response (real status, no checks)
const summary = await handle({});
// { status: 200, body: { status: 'healthy', timestamp: '...', build: 'stg-45d76e5' } }

// resolveDetail returns 'full' → full response with check details
const full = await handle({ queryParams: { token: '...' } });
// { status: 200, body: { status: 'healthy', timestamp: '...', build: 'stg-45d76e5', checks: { ... } } }

Summary / Full Responses

Health checks always run. The resolveDetail option controls how much detail is exposed in the response:

| resolveDetail returns | Response | |-------------------------|----------| | 'summary' (or omitted) | Summary — real HTTP status with { status: "healthy"/"degraded"/"outage", timestamp, ...metadata } | | 'full' | Full — real HTTP status with check results + metadata |

When resolveDetail is not provided, the handler returns a summary response.

The resolveDetail function receives the request object ({ ip, headers, queryParams, authorizationHeader }) and returns 'full' or 'summary' (or a promise of either). This lets you implement any detail policy — token-based, IP-based, header-based, or always-full for internal services:

// Always full (internal service behind a private network)
createHealthcheckHandler({
  registry,
  resolveDetail: () => 'full',
});

Both summary and full responses reflect real health status and return the correct HTTP status code (200 for healthy, 503 for degraded/outage). The summary response lets load balancers and uptime monitors get real health status without exposing internal check details. The full response adds the checks object with per-check diagnostics.

Metadata

Attach static key-value pairs that appear in both summary and full responses:

createHealthcheckHandler({
  registry,
  metadata: {
    build: 'stg-45d76e5',
    buildTimestamp: '2025-02-25T19:41:56Z',
    region: 'us-east-1',
  },
});

Metadata values can be string, number, or boolean. Keys status, timestamp, checks, and cachedAt are reserved -- passing them throws at handler creation time.

summaryMetadata

By default, summary responses include all metadata fields. Use summaryMetadata to override what appears in summary responses while keeping metadata for full responses:

createHealthcheckHandler({
  registry,
  metadata: {
    build: 'stg-45d76e5',
    buildTimestamp: '2025-02-25T19:41:56Z',
    region: 'us-east-1',
  },
  // Summary responses only include status + timestamp (no build info)
  summaryMetadata: {},
});

You can also include a subset of fields:

createHealthcheckHandler({
  registry,
  metadata: { build: 'stg-45d76e5', region: 'us-east-1', version: '1.0.0' },
  // Summary responses include only version
  summaryMetadata: { version: '1.0.0' },
});

When summaryMetadata is omitted, summary responses fall back to using metadata.

Utilities

extractToken and verifyToken are exported helpers for use inside your resolveDetail function.

import { verifyToken, extractToken } from '@firebreak/vitals';

// Extract a token from query params (?token=...) or Authorization header
const token = extractToken({
  queryParams: { token: 'abc' },
  authorizationHeader: 'Bearer abc',
});

// Timing-safe SHA-256 comparison
verifyToken('provided-token', 'expected-token'); // boolean

Response Format

Summary response (resolveDetail returns 'summary' or is omitted):

{
  "status": "healthy",
  "timestamp": "2025-02-26T12:00:00.000Z",
  "build": "stg-45d76e5",
  "buildTimestamp": "2025-02-25T19:41:56Z"
}

Full response (resolveDetail returns 'full'):

{
  "status": "healthy",
  "timestamp": "2025-02-26T12:00:00.000Z",
  "build": "stg-45d76e5",
  "buildTimestamp": "2025-02-25T19:41:56Z",
  "checks": {
    "postgres": {
      "status": "healthy",
      "latencyMs": 4,
      "message": ""
    },
    "redis": {
      "status": "healthy",
      "latencyMs": 1,
      "message": ""
    }
  }
}

Both summary and full responses return real HTTP status codes:

| Status | HTTP Code | |--------|-----------| | "healthy" | 200 | | "degraded" | 503 | | "outage" | 503 |

Requirements

  • Node.js >= 20.0.0