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

@watchmecode/retrace-sdk

v0.4.0

Published

Capture backend events (HTTP, DB, jobs, external & LLM calls) and replay failures on a visual timeline. Fastify plugin + manual client, with automatic trace context via AsyncLocalStorage.

Readme

@watchmecode/retrace-sdk

Capture backend events and replay failures on a visual timeline.

The SDK sends structured events (HTTP requests, DB queries, job/queue steps, external & LLM calls, errors) to a ReTrace API. Events that share a traceId are grouped server-side into a single incident — one failed request/flow = one timeline you can scrub through.

Install

npm install @watchmecode/retrace-sdk

Quick start (Fastify)

import Fastify from 'fastify'
import { fastifyRetrace } from '@watchmecode/retrace-sdk'

const app = Fastify()

await app.register(
  fastifyRetrace({
    apiUrl: 'https://your-retrace-api',
    apiKey: process.env.RETRACE_API_KEY, // rtrace_xxx — ties events to your project
    captureBody: true,
    errorThreshold: 400, // open an incident on any 4xx/5xx
  })
)

Every request is now captured automatically: an HTTP_REQUEST event named "<METHOD> <route> → <status>", plus a full stack trace for unhandled (5xx) errors. Handled client errors (4xx) are recorded once, via the response — no duplicate noise.

Quick start (Express)

The same core, exposed as Express middleware via a subpath import:

import express from 'express'
import { expressRetrace } from '@watchmecode/retrace-sdk/express'

const app = express()
app.use(express.json())

const retrace = expressRetrace({
  apiUrl: 'https://your-retrace-api',
  apiKey: process.env.RETRACE_API_KEY,
  captureBody: true,
})
app.use(retrace)                 // capture every request + bind trace context

// ...your routes...

app.use(retrace.errorHandler)    // optional: capture unhandled (5xx) errors with a stack

Behaviour matches the Fastify plugin (same events, redaction, and automatic trace context below). express is an optional peer dependency — it's only loaded through the /express subpath, so Fastify users never pull it in.

Quick start (NestJS)

A global interceptor + module, wired in one line:

import { Module } from '@nestjs/common'
import { RetraceModule } from '@watchmecode/retrace-sdk/nestjs'

@Module({
  imports: [
    RetraceModule.forRoot({
      apiUrl: 'https://your-retrace-api',
      apiKey: process.env.RETRACE_API_KEY,
      captureBody: true,
    }),
  ],
})
export class AppModule {}

RetraceModule.forRoot() registers a global APP_INTERCEPTOR that captures every request (with the same events, redaction, and trace context) and reports HttpException statuses correctly. Inject the shared client with @Inject(RETRACE_CLIENT) for manual captures. @nestjs/* and rxjs are optional peers, loaded only via the /nestjs subpath.

✨ Automatic trace context (AsyncLocalStorage)

The headline feature. The Fastify plugin binds the request's traceId to its async context, so manual captures anywhere in the call chain auto-correlate to the same incident — you never thread a traceId through your function signatures.

import { createClient } from '@watchmecode/retrace-sdk'

const retrace = createClient({ apiUrl, apiKey })

app.post('/checkout', async (req, reply) => {
  await chargeCard()       // ← captures inside here…
  await reserveStock()     // ← …and here…
  // …all land in the SAME incident as this request, no traceId passed around.
})

async function chargeCard() {
  try {
    await gateway.charge()
  } catch (err) {
    retrace.captureException(err, { source: 'payment-gateway', label: 'charge' })
    throw err
  }
}

Outside an HTTP request (background jobs, queue consumers) open a scope yourself:

import { runWithTrace, generateTraceId } from '@watchmecode/retrace-sdk'

await runWithTrace({ traceId: generateTraceId() }, async () => {
  await processJob()       // every capture inside joins one incident
})

Manual capture API

// A single event. incidentId/traceId are optional — omit them and the API
// groups by the active trace context.
retrace.capture({
  type: 'DB_QUERY',
  source: 'inventory-service',
  label: 'inventory.lock',
  status: 'SUCCESS',
  durationMs: 42,
})

// An error with message + stack, status ERROR. Trace context is resolved
// automatically.
retrace.captureException(err, { source: 'worker', label: 'job failed' })

Options

| Option | Default | Description | | ---------------- | ------------------------------- | -------------------------------------------- | | apiUrl | — | Base URL of the ReTrace API (required) | | apiKey | — | rtrace_… key; ties events to your project | | errorThreshold | 500 | HTTP status ≥ this marks the event an error | | captureBody | false | Capture request/response bodies | | captureHeaders | false | Capture HTTP headers | | maxBodySize | 8000 | Truncate captured bodies to N bytes | | redactHeaders | authorization, cookie, … | Header names redacted from captured metadata | | redactFields | password, token, secret, … | Body/payload field names whose values are redacted |

Redaction

Telemetry should never leak secrets. Before anything is sent:

  • Sensitive headers are replaced with [REDACTED] (redactHeaders).
  • Sensitive body/payload fields are recursively redacted by field name — through nested objects and arrays — for both auto-captured request bodies and manual capture() payloads/metadata (redactFields). Matching is case-insensitive and ignores separators, so apiKey, api_key and API-KEY all match. Defaults cover passwords, tokens, secrets, keys, cookies, session ids, card numbers, CVV, SSN, and similar.
createClient({ apiUrl, redactFields: ['password', 'token', 'x-internal-id'] })
// { user: 'ann', password: 'hunter2' } → { user: 'ann', password: '[REDACTED]' }

Notes

  • All sends are fire-and-forget — capturing never throws and never blocks your request path.
  • Sensitive headers and body fields are redacted by default; bodies are also truncated to maxBodySize.