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

@newinstance/bugwatch-tanstack

v0.1.0

Published

BugWatch adapter for TanStack Query. Captures query and mutation failures, leaves a breadcrumb trail, and traces requests, on React Web and React Native.

Readme

@newinstance/bugwatch-tanstack

BugWatch adapter for TanStack Query. Point it at a QueryClient and every failed query and mutation is reported to BugWatch, with the operation that failed, a breadcrumb trail of what led there, and a span for the request.

Works on React Web and React Native.

npm install @newinstance/bugwatch-tanstack

You also need TanStack Query and the BugWatch SDK for your platform:

# React Web
npm install @tanstack/react-query @newinstance/bugwatch

# React Native
npm install @tanstack/react-query @newinstance/bugwatch-react-native

Quick start

Initialise BugWatch as you normally would, then instrument the client once, where you create it.

React Web

import { QueryClient } from '@tanstack/react-query';
import { BugWatch } from '@newinstance/bugwatch';
import { instrumentQueryClientWithBugWatch } from '@newinstance/bugwatch-tanstack/web';

BugWatch.init({ dsn: process.env.BUGWATCH_DSN! });

export const queryClient = new QueryClient();
instrumentQueryClientWithBugWatch(queryClient);

React Native

import { QueryClient } from '@tanstack/react-query';
import { BugWatch } from '@newinstance/bugwatch-react-native';
import { instrumentQueryClientWithBugWatch } from '@newinstance/bugwatch-tanstack/native';

BugWatch.init({ dsn: BUGWATCH_DSN });

export const queryClient = new QueryClient();
instrumentQueryClientWithBugWatch(queryClient);

That is the whole integration. Nothing else in your app changes, and no query or mutation needs to know BugWatch exists.

What you get

| | Reported | |---|---| | Failed query | The error, tagged with the operation name and retry count, with the query key as context | | Failed mutation | The same, from the mutation key | | Breadcrumbs | Every query and mutation start, success and failure, in order, so a captured error arrives with the trail that led to it | | Spans | One span per query and mutation, with duration and failure status (web only, see below) |

Instrumenting returns a function that removes it again:

const stop = instrumentQueryClientWithBugWatch(queryClient);
stop();

Platform differences, stated plainly

The two BugWatch SDKs are not identical, and this adapter does not pretend otherwise.

| | Web (@newinstance/bugwatch) | React Native (@newinstance/bugwatch-react-native) | |---|---|---| | Error capture | Yes | Yes | | Breadcrumbs | Yes | Yes | | Per-error tags | Yes | No: the native SDK's captureException takes a level only | | Structured context | Yes, an object | Serialized to a string, since the native SDK takes strings | | Spans / tracing | Yes | No: the native SDK has no span API |

Tracing is on by default. On React Native it is silently unavailable, so pass onWarning if you want to hear about it rather than wonder:

instrumentQueryClientWithBugWatch(queryClient, {
  onWarning: (message) => console.warn(message),
});

Errors and breadcrumbs still work on React Native; only spans are missing. The returned function carries tracingActive if you want to branch on it.

Keeping personal data out of BugWatch

Query keys routinely contain user ids, emails and search terms, and they are recorded with every captured error. redactKey runs before anything leaves your app:

instrumentQueryClientWithBugWatch(queryClient, {
  redactKey: (key) =>
    key.map((part) =>
      typeof part === 'string' && part.includes('@') ? '[redacted]' : part,
    ),
});

Mutation variables are never recorded by default, because that is where card numbers and passwords live. Opt in only where you know the payload is safe:

instrumentQueryClientWithBugWatch(queryClient, { includeMutationVariables: true });

redactKey is applied to variables too when you do.

Not reporting expected failures

A 404 from a lookup is usually not a bug. shouldCapture decides:

instrumentQueryClientWithBugWatch(queryClient, {
  shouldCapture: (error, context) => {
    if (error instanceof HttpError && error.status === 404) return false;
    if (context.kind === 'query' && context.operationName === 'presence') return false;
    return true;
  },
});

Filtered errors still leave a breadcrumb, so the trail stays complete even when the error itself is not worth an issue.

Options

| Option | Default | Notes | |---|---|---| | captureQueryErrors | true | Report failed queries | | captureMutationErrors | true | Report failed mutations | | breadcrumbs | true | Record the lifecycle trail | | tracing | true | Span per operation. Web only | | redactKey | none | (key, kind) => key, applied before recording | | shouldCapture | none | (error, context) => boolean | | includeMutationVariables | false | Off because payloads carry secrets | | maxKeyLength | 256 | Serialized keys are truncated past this | | onWarning | none | Called when a requested feature is unavailable |

Using a custom target

instrumentQueryClient takes any object implementing BugWatchTarget, which is useful for tests or for routing to your own sink:

import { instrumentQueryClient } from '@newinstance/bugwatch-tanstack';

instrumentQueryClient(queryClient, {
  platform: 'web',
  capabilities: { captureTags: true, tracing: false, richContext: true },
  captureException: (error) => myReporter.report(error),
  addBreadcrumb: (crumb) => myReporter.trail(crumb),
  setContext: (key, data) => myReporter.context(key, data),
});

It will not break your app

Every call into BugWatch is wrapped. If the SDK is missing, misconfigured or throws, your queries and mutations resolve and reject exactly as they would without this package. A monitoring tool that can take down the thing it monitors is worse than no monitoring, so that behaviour is covered by tests.

One limitation worth knowing: TanStack Query hashes query keys with JSON.stringify, so a circular query key throws inside TanStack itself, before this adapter is ever involved. Keys with Date, Map or undefined values are handled.

License

MIT