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

@subnomic/bugfree-js

v0.9.6

Published

bugfree SDK for browser applications, with Vue, React or no framework

Readme

@subnomic/bugfree-js

The bugfree SDK for browser applications: plain pages, Vue, React and any other framework. It reports uncaught errors and rejected promises with the steps that led to them, and resolves minified frames back to your source.

npm install @subnomic/bugfree-js    # or: bun add @subnomic/bugfree-js

It runs in the browser; it does not report from Node.js.

Setup

// bugfree.js
import { create_bugfree } from '@subnomic/bugfree-js'

export const bugfree = create_bugfree({
  dsn: import.meta.env.VITE_BUGFREE_DSN, // http://<key>@host:3000/ingest
  environment: import.meta.env.MODE,
  release: '[email protected]',
})

// window.onerror + unhandledrejection, and breadcrumbs for fetch, XHR,
// WebSocket connections, clicks, page changes and the console
bugfree.install()

An empty dsn disables the SDK: nothing is installed and every call is a no-op.

Vue

Pass the application and the router to install instead, before mounting. Component errors then go through Vue's errorHandler, and route changes become breadcrumbs:

const app = createApp(App)
bugfree.install(app, router)
app.use(router).mount('#app')

React

Errors React does not catch reach the global handlers. Errors an error boundary catches stay inside React; report them from the root (React 19):

createRoot(document.getElementById('root'), {
  onCaughtError(error, info) {
    bugfree.capture_exception(error, { extra: { component_stack: info.componentStack } })
    console.error(error)
  },
}).render(<App />)

Other frameworks

install() sees every error that reaches the page. Where a framework catches errors itself, such as Angular's ErrorHandler, call capture_exception there.

Capturing

bugfree.capture_exception(error, { tags: { step: 'checkout' } })
bugfree.capture_message('cart recovered', { level: 'info' })

bugfree.set_user({ id: user.id, email: user.email })
bugfree.set_tag('plan', 'team')
bugfree.set_tag('plan', null)   // null or undefined removes a tag
bugfree.add_breadcrumb({ category: 'ui', message: 'clicked pay' })

await bugfree.flush()   // before navigating away

Both capture calls return a promise of the event id (null when nothing was sent); bugfree.last_event_id() has it as soon as the call returns, to show the user as a reference. An error created with { cause } lists its causes on the issue.

User feedback

// A dialog that asks what happened, tied to the latest captured event
await bugfree.show_feedback_dialog({ labels: { title: 'Sorry, that did not work' } })

// Or from a form of your own
await bugfree.capture_feedback({ message, email })

Every event carries the browser context under extra.browser: viewport and screen size, language, online state and connection type.

Clicks are recorded by selector only (tag, id, classes, name or aria-label), never by the text on the page. When the page is left, events still waiting are handed to sendBeacon. A 429 answer pauses sending for as long as its Retry-After asks, a minute when it names no time.

Original source instead of minified frames

Browser stack traces point at the bundle (/assets/index-abc.js:1:24815). The SDK downloads that file's .map, decodes the mappings itself and reads the original code from sourcesContent, so the issue page shows your original file (.vue, .tsx, .js), the real line number and the surrounding code.

Enable source maps in the build:

// vite.config.js
build: { sourcemap: true }

Frames that cannot be resolved (no map published, or a generated line with no mapping) are sent as-is — an error is never dropped because of a missing map.

Published source maps are readable by anyone who can load the app. If that is not acceptable, upload them to the release on your bugfree server instead, leave them out of the deployment and set resolve_source_maps: false.

Without sending the code

A map carries the complete original source in sourcesContent. To keep the code out of bugfree altogether, remove it before uploading the maps to the release:

npx -p @subnomic/bugfree-js bugfree-strip-sources dist/assets

Every .map under the folder keeps its mappings, sources and names, so frames still resolve to the original file, line and function; only the lines around the failing one are not shown. With a GitHub integration and a release created with its commit_sha, such a frame opens on GitHub at that commit instead. The link uses the paths the build wrote: in a monorepo, write them from the repository root, for instance with Vite's build.rollupOptions.output.sourcemapPathTransform.

Scrubbing addresses

A page opened from an emailed link carries its token in the address, and the SDK sends addresses in many places: the request of an event, fetch, XHR and navigation breadcrumbs, span descriptions and the page load's name, replays (the page address, links and form targets), the scripts a profile lists, and feedback. scrub_url sees each of them before it leaves the browser, and before before_send and before_send_transaction:

create_bugfree({
  dsn: import.meta.env.VITE_BUGFREE_DSN,
  scrub_url: (url) => url.replace(/\/invite\/[^/?#]+/, '/invite/:token').replace(/([?&]token=)[^&#]+/, '$1:token'),
})

A hook that throws, or returns anything but a string, sends [Filtered] in place of the address. The addresses of the scripts in stack frames are left as they are: source maps are found by them.

Content Security Policy

A request the page's policy blocks leaves no trace on any server. The SDK records every violation as a breadcrumb (category csp: the directive, the blocked address and the script that tried), and with report_csp_violations: true sends it as a warning event too, one issue per directive and blocked origin. Violations caused by browser extensions are left out.

Pages without the SDK can report the same way: point the policy at the project's csp address, which takes both report formats.

Reporting-Endpoints: bugfree="https://bugfree.example.com/ingest/v1/<public-key>/csp"
Content-Security-Policy: default-src 'self'; report-uri https://bugfree.example.com/ingest/v1/<public-key>/csp; report-to bugfree

Options

| Option | Default | Meaning | |---|---|---| | environment | 'production' | Environment tag. | | release | '' | Release tag used for grouping and regressions. | | sample_rate | 1 | Fraction of events to send. | | source_context_lines | 5 | Lines shown around the failing line. | | resolve_source_maps | true | Resolve minified frames through .map files. | | max_breadcrumbs | 30 | Ring buffer size. | | dedupe_window_ms | 10000 | Same error is sent once per window. | | ignore_errors | [] | Strings or RegExps; drops errors whose Type: message matches. | | traces_sample_rate | 0 | Share of page loads and navigations timed, with requests as spans and web vitals; a route's INP is sent when it is left or the page is hidden, as a ui.interaction transaction of its trace. | | replays_on_error_sample_rate | 0 | Share of page loads that keep their last minute of session replay and send it with an error. | | replays_session_sample_rate | 0 | Share of page loads recorded as a session replay from start to end. | | replay_mask_all_text | true | Mask every text in replays (input values are always masked). | | profiles_sample_rate | 0 | Share of timed transactions profiled with the JS Self-Profiling API (Chromium, page served with Document-Policy: js-profiling). A profile is sent only with its transaction. | | trace_propagation_targets | [] | Other origins whose requests carry the traceparent header. | | track_sessions | true | Report every page load as a session of the release, for release health. | | deny_urls | [] | Strings or RegExps; drops errors thrown by scripts at these addresses. | | report_csp_violations | false | Send every Content-Security-Policy violation as a warning event; see Content Security Policy. | | scrub_url | null | Rewrites every address the SDK sends before the other hooks run; see Scrubbing addresses. | | before_send | null | Return null to drop, or edit the event. | | before_send_transaction | null | The same for a timed transaction, which before_send never sees: its spans carry request and resource addresses, query string included. | | debug | false | Warn to the console about SDK problems. |

Tests

node --test test/*.test.mjs

Releasing

The SDK is published to github.com/subnomic/bugfree-js-sdk, with this directory as that repository's root, and to npm, by the bugfree release: one release on the bugfree repository's Releases page with the tag v0.9.6 publishes the server and both SDKs at that version. Raise version in package.json and VERSION in src/index.js with the others.

The release workflow checks that both versions match the tag, runs the tests, pushes this directory to that repository as one commit, tags it there as v0.9.6 and publishes the package to npm (under next for a pre-release).

License

MIT, see LICENSE.