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

flarewatch

v0.1.0

Published

Lightweight error tracking, performance monitoring and custom logging for React + Vite apps

Readme

🔥 flarewatch

Lightweight error tracking, performance monitoring and custom logging for React + Vite apps.

npm version bundle size license


Funcionalidades

  • ✅ Captura de erros de render React (ErrorBoundary integrado)
  • ✅ Erros JS globais (window.onerror)
  • ✅ Promises rejeitadas sem .catch()
  • ✅ Erros de API (fetch wrapper)
  • ✅ Web Vitals: LCP, FID, CLS, FCP, TTFB — com severidade automática
  • ✅ Logs customizados: info, warn, error, debug
  • ✅ Transports plugáveis (HTTP, Console, ou crie o seu)
  • ✅ Batch + retry + fallback offline (localStorage)
  • beforeSend hook para filtrar/enriquecer eventos
  • ✅ TypeScript first — 100% tipado

Instalação

npm install flarewatch
# ou
pnpm add flarewatch

Setup rápido

1. Modo init() — entry point do Vite

// src/main.ts
import { init, httpTransport, consoleTransport } from "flarewatch";

init({
  transports: [
    httpTransport({ url: "https://seu-backend.com/api/errors" }),
    consoleTransport({ minLevel: "warning" }), // só em dev
  ],
  defaultContext: {
    appVersion: import.meta.env.VITE_APP_VERSION,
    environment: import.meta.env.MODE,
  },
  debug: import.meta.env.DEV,
});

2. Modo <FlarewatchProvider> — com React

// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { FlarewatchProvider } from "flarewatch/react";
import { httpTransport, consoleTransport } from "flarewatch";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <FlarewatchProvider
    config={{
      transports: [
        httpTransport({ url: "/api/errors" }),
        consoleTransport(),
      ],
    }}
    fallback={<div>Algo deu errado.</div>}
  >
    <App />
  </FlarewatchProvider>
);

Logs customizados

import { useFlarewatch } from "flarewatch/react";

function MyComponent() {
  const fw = useFlarewatch();

  const handleCheckout = async () => {
    fw.info("Checkout iniciado", { cartItems: 3 });

    try {
      await processPayment();
      fw.info("Pagamento aprovado");
    } catch (err) {
      fw.error(err as Error, { step: "payment" });
    }
  };
}

Sem Provider (após init()):

import { getClient } from "flarewatch";

const fw = getClient();
fw.warn("Cache expirado", { key: "user-preferences" });

Fetch com captura automática

import { useFlarewatchFetch } from "flarewatch/react";

function UsersList() {
  const apiFetch = useFlarewatchFetch();

  useEffect(() => {
    // erros HTTP 4xx/5xx e falhas de rede chegam automático no backend
    apiFetch("/api/users")
      .then(r => r.json())
      .then(setUsers);
  }, []);
}

Ou sem hooks:

import { getClient } from "flarewatch";

const fw = getClient();
const res = await fw.fetch("/api/products");

Transports

httpTransport(options)

| Opção | Tipo | Padrão | Descrição | |---|---|---|---| | url | string | — | Obrigatório. Endpoint que recebe os eventos | | headers | object | {} | Headers extras (Authorization, etc) | | batchMs | number | 2000 | Debounce em ms antes de enviar o batch | | batchSize | number | 20 | Força envio quando atingir N eventos | | timeout | number | 8000 | Timeout da requisição em ms | | retries | number | 3 | Tentativas com backoff exponencial | | offlineFallback | boolean | true | Salva no localStorage quando offline |

consoleTransport(options)

| Opção | Tipo | Padrão | Descrição | |---|---|---|---| | minLevel | Severity | "debug" | Nível mínimo para exibir | | verbose | boolean | false | Exibe o objeto completo do evento |

Criar transport customizado

import type { Transport } from "flarewatch";

const datadogTransport: Transport = {
  name: "datadog",
  send(event) {
    DD_LOGS.logger.log(event.message, event.context, event.severity);
  },
};

init({ transports: [datadogTransport] });

beforeSend — filtrar ou enriquecer eventos

init({
  transports: [...],
  beforeSend(event) {
    // descartar erros de extensões de browser
    if (event.stack?.includes("chrome-extension://")) return false;

    // enriquecer com dados do usuário logado
    return {
      ...event,
      context: {
        ...event.context,
        userId: store.getState().user.id,
      },
    };
  },
});

Configuração completa

init({
  transports: [
    httpTransport({
      url: "/api/errors",
      headers: { Authorization: `Bearer ${token}` },
      batchMs: 3000,
      batchSize: 30,
      retries: 3,
    }),
    consoleTransport({ minLevel: "warning", verbose: true }),
  ],
  captureGlobalErrors: true,
  captureUnhandledRejections: true,
  capturePerformance: true,
  minLogLevel: "info",
  defaultContext: {
    appVersion: "1.2.3",
    environment: "production",
    userId: getCurrentUser()?.id,
  },
  beforeSend(event) {
    if (event.type.startsWith("perf.") && event.severity === "info") return false;
    return event;
  },
  debug: false,
});

Payload enviado ao backend

{
  "id": "fw-lq3k2-abc12",
  "type": "error.api",
  "severity": "error",
  "message": "HTTP 500 Internal Server Error",
  "stack": "Error: HTTP 500...",
  "url": "https://seuapp.com/dashboard",
  "userAgent": "Mozilla/5.0 ...",
  "timestamp": "2026-03-23T14:00:00.000Z",
  "sessionDuration": 42,
  "context": {
    "endpoint": "/api/users",
    "status": 500,
    "method": "GET",
    "appVersion": "1.2.3",
    "userId": "user-456"
  }
}

Web Vitals — thresholds de severidade

| Métrica | info (bom) | warning (precisa melhorar) | error (ruim) | |---|---|---|---| | LCP | ≤ 2500ms | ≤ 4000ms | > 4000ms | | FID | ≤ 100ms | ≤ 300ms | > 300ms | | CLS | ≤ 0.1 | ≤ 0.25 | > 0.25 | | FCP | ≤ 1800ms | ≤ 3000ms | > 3000ms | | TTFB | ≤ 800ms | ≤ 1800ms | > 1800ms |


License

MIT