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

@nreactive/fastify

v0.2.0

Published

Fastify plugin for @nreactive/core — automatic request-context propagation and error capture

Readme

@nreactive/fastify

Fastify 4/5 plugin for @nreactive/core — automatic request-context propagation and error capture for the nreactive AI error-fix pipeline.

  • Registers onRequest + onError hooks that attach method, url, request ID, route, and scrubbed headers to any error captured during handling.
  • Uses Fastify's built-in async context propagation — no extra async_hooks bookkeeping.
  • Zero runtime dependencies of its own — just @nreactive/core (peer) and Fastify.
  • Works with Fastify 4 and 5. Node ≥ 20.

Install

npm install @nreactive/core @nreactive/fastify
# or: pnpm add @nreactive/core @nreactive/fastify
# or: yarn add @nreactive/core @nreactive/fastify
# or: bun add @nreactive/core @nreactive/fastify

AI-assisted setup

Paste the prompt below into Claude Code, Cursor, Copilot, or any agent with file-write access. It has enough information to finish the integration end-to-end — no manual wiring required.

You are adding the @nreactive/core + @nreactive/fastify SDKs to this Fastify project. nreactive is a production error-monitoring service that opens AI-generated pull requests to fix the errors it catches.

  1. Detect the package manager from the lockfile (package-lock.json → npm, pnpm-lock.yaml → pnpm, yarn.lock → yarn, bun.lockb → bun).
  2. Install @nreactive/core and @nreactive/fastify with that package manager.
  3. Create a file src/observability/nreactive.ts (or .js if the project is not TypeScript) that imports init from @nreactive/core and calls it with { appId: process.env.NREACTIVE_APP_ID, environment: process.env.NODE_ENV, release: process.env.APP_VERSION }. Export nothing — the module is used for its import side effect.
  4. In the server entry file (commonly src/index.ts, src/server.ts, or the main field of package.json), add import "./observability/nreactive"; as the very first import, before any framework imports including fastify.
  5. In the Fastify app setup, register the plugin as early as possible: await app.register((await import("@nreactive/fastify")).default). Do this before registering user routes so the onRequest hook fires for every request.
  6. Add NREACTIVE_APP_ID= to .env.example (create it if missing) and document the variable in the README's environment-variables section. The user will obtain their App ID from https://nreactive.com/dashboard/apps.
  7. Do not invent additional configuration. Restart the server and throw a test error from a route to confirm events appear in the nreactive dashboard.

Stop and ask if the project structure doesn't match these assumptions (for example, if the project is not using Fastify).

Quick start

// src/observability/nreactive.ts — imported FIRST in your entry file
import { init } from "@nreactive/core";

init({
  appId: process.env.NREACTIVE_APP_ID!,
  environment: process.env.NODE_ENV,
  release: process.env.APP_VERSION,
});
// src/server.ts
import "./observability/nreactive";        // ← must be the first import

import Fastify from "fastify";
import nreactivePlugin from "@nreactive/fastify";

const app = Fastify({ logger: true });

await app.register(nreactivePlugin);        // register BEFORE routes

app.get("/", async () => ({ hello: "world" }));

await app.listen({ port: 3000 });

Get your App ID from the nreactive dashboard.

How it works

  • onRequest hook — fires very early in Fastify's lifecycle and calls addContext({...}) so any captureException triggered during handling automatically includes:
    • method (uppercased)
    • url (with query params scrubbed)
    • requestId (Fastify's req.id, else X-Request-ID header, else randomUUID())
    • route (from req.routeOptions.url or req.routerPath)
    • headers (scrubbed)
  • onError hook — captures every error Fastify emits from a route or plugin, classifies severity via @nreactive/core, and forwards it to the ingest pipeline.

API

Default export — the plugin

import nreactivePlugin from "@nreactive/fastify";

await app.register(nreactivePlugin, {
  // Header names to redact. Merged with @nreactive/core defaults.
  scrubHeaders: ["authorization", "x-api-key"],
  // Query param names to redact in the URL. Merged with core defaults.
  scrubQueryParams: ["token", "secret"],
  // Emit an `http.server` breadcrumb for each request. Default: true.
  breadcrumbs: true,
});

Options type:

interface NreactivePluginOptions {
  scrubHeaders?: string[];
  scrubQueryParams?: string[];
  breadcrumbs?: boolean;
}

A named export plugin is also provided for CJS consumers that prefer destructuring:

const { plugin } = require("@nreactive/fastify");

Attaching user context

Fastify doesn't put auth info on req.user by convention, so you call addContext yourself in a hook or route:

import { addContext } from "@nreactive/core";

app.addHook("preHandler", async (req) => {
  const user = await resolveUser(req);
  if (user) addContext({ user: { id: user.id, email: user.email } });
});

Because @nreactive/fastify registers its onRequest hook first, your preHandler runs inside the context frame it opened — the user info merges into the active store, not a detached one.

Full example

import "./observability/nreactive";

import Fastify from "fastify";
import nreactivePlugin from "@nreactive/fastify";
import { captureException, addContext } from "@nreactive/core";

const app = Fastify({ logger: true });

await app.register(nreactivePlugin, {
  scrubHeaders: ["authorization", "x-session-token"],
});

app.addHook("preHandler", async (req) => {
  const session = await getSession(req);
  if (session) addContext({ user: { id: session.userId } });
});

app.get("/boom", async () => {
  throw new Error("intentional test error");
});

app.get("/manual", async (req, reply) => {
  try {
    doWork();
    return { ok: true };
  } catch (err) {
    captureException(err, "error", { tags: { route: "/manual" } });
    reply.code(500);
    return { ok: false };
  }
});

await app.listen({ port: 3000 });

Links

License

PROPRIETARY. See LICENSE.