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

@browsonic/vue

v1.3.0

Published

Vue 3 adapter for @browsonic/sdk — error boundary, composables, app plugin with errorHandler chaining. Apache-2.0.

Downloads

433

Readme

@browsonic/vue

Vue 3 adapter for @browsonic/sdk — error boundary component, composables, an app.use() plugin that chains into app.config.errorHandler, Vue Router instrumentation, and a Pinia integration.

Status: 0.3 surface — boundary, four composables (useBrowsonic / useUser / useCaptureError / useBreadcrumb), plugin install, Vue Router 4 navigation breadcrumbs (with optional beforeEach intent phase), Pinia plugin that stamps store action errors with context. Server-side rendering capture is intentionally out of scope (browser-runtime adapter only).

Why this adapter

Vue's reconciler captures render-time and lifecycle exceptions in descendant components and routes them through errorCaptured / app.config.errorHandler. The plain @browsonic/sdk install therefore never hears about them — only the global error / unhandledrejection events. This package closes that gap.

Install

npm install @browsonic/sdk @browsonic/vue

@browsonic/sdk is a peer dependency. vue (3.3+) is a peer dependency.

Quickstart

import { createApp } from 'vue';
import { getBrowsonic } from '@browsonic/sdk';
import { browsonicPlugin, BrowsonicErrorBoundary } from '@browsonic/vue';
import App from './App.vue';

const sdk = getBrowsonic();
sdk.init({ apiEndpoint: 'https://your-ingest-endpoint.test/v1/events' });

const app = createApp(App);
app.use(browsonicPlugin, { sdk });
app.component('BrowsonicErrorBoundary', BrowsonicErrorBoundary);
app.mount('#app');

Wrap the parts of your tree you want to isolate:

<BrowsonicErrorBoundary :fallback="ErrorScreen">
  <Routes />
</BrowsonicErrorBoundary>

API

browsonicPlugin

app.use(browsonicPlugin, {
  sdk, // optional; falls back to window.Browsonic.getBrowsonic()
  chainErrorHandler: true, // optional; default true — chains into app.config.errorHandler
});

Wires provide(browsonicInjectionKey, sdk) so composables can resolve via inject, and chains into app.config.errorHandler so errors that aren't caught by a boundary still reach the SDK. The previously-installed handler is preserved and called after the report.

<BrowsonicErrorBoundary>

<BrowsonicErrorBoundary :fallback="(ctx) => h('div', 'Crashed: ' + ctx.error.message)">
  <Inner />
</BrowsonicErrorBoundary>

Props:

| Prop | Type | Required | | ---------- | --------------------------------------------------- | -------- | | fallback | Component \| ((ctx: { error, reset }) => unknown) | yes | | sdk | Browsonic | no | | onError | (error: Error, info: string) => void | no |

When a child throws during render or in a lifecycle hook, the boundary forwards the error to the SDK (truncating any component stack to 1024 characters as componentStack metadata) and then renders the fallback. Returning false from errorCaptured stops further propagation.

useBrowsonic() / useUser() / useCaptureError() / useBreadcrumb()

import { useBrowsonic, useUser, useCaptureError, useBreadcrumb } from '@browsonic/vue';

const sdk = useBrowsonic();
useUser({ id: 'u1', email: '[email protected]' });

const captureError = useCaptureError();
const addBreadcrumb = useBreadcrumb();
function onClick() {
  addBreadcrumb({ category: 'ui.click', message: 'buy button' });
  try {
    risky();
  } catch (err) {
    captureError(err as Error);
  }
}

useUser accepts a plain value or a Ref (re-applies on change, immediate). All four composables are no-ops when the SDK is unreachable.

installRouterInstrumentation(router, options?)

Subscribes to a Vue Router 4 afterEach guard and emits a category: 'navigation' breadcrumb on every successful route change. Pass { includeIntent: true } to also subscribe to beforeEach and emit a phase: 'intent' breadcrumb before the navigation begins (the existing afterEach breadcrumb gets phase: 'completed'). Returns the unsubscribe handle from Vue Router for HMR-friendly teardown.

import { createRouter, createWebHistory } from 'vue-router';
import { installRouterInstrumentation } from '@browsonic/vue';

const router = createRouter({ history: createWebHistory(), routes: [...] });
const off = installRouterInstrumentation(router, { includeIntent: true });
// optional: off() during HMR teardown

Structural RouterLike shape — no vue-router runtime dep. Intent breadcrumbs are the only record of an attempted route when an error fires mid-navigation, so includeIntent: true is recommended for production observability.

installPiniaIntegration(pinia, options?)

Pinia plugin that hooks every store's $onAction.onError so unhandled action errors stamp the SDK scope with setContext('pinia', { storeId, action, args, errorMessage, state? }) before bubbling. The Vue boundary or window error handler then captures an event that already knows which store + action caused the failure.

import { createPinia } from 'pinia';
import { installPiniaIntegration } from '@browsonic/vue';

const pinia = createPinia();
installPiniaIntegration(pinia, {
  // Opt-in: include store state snapshot. Off by default — Pinia stores
  // commonly hold auth tokens / PII; audit per app before enabling.
  captureState: false,
  // Skip specific stores by `$id` (auth / wallet stores benefit).
  ignoreStores: ['auth'],
});
app.use(pinia);

Structural PiniaLike / PiniaStoreLike — no pinia runtime dep. maxLength (default 4096) caps serialised args / state to keep event payload size bounded.

Defensive contract

Every public surface follows the same rule:

  • The host app must never crash because reporting failed.
  • SDK calls are wrapped in try { ... } catch {}. If the boundary, plugin, or composable can't reach the SDK, it stays silent.
  • Composables and the boundary work without the plugin — they fall back to window.Browsonic.getBrowsonic().

What this package does NOT do

  • Server-side rendering capture. Out of scope. The SDK is a browser library; the adapter is a browser library.
  • Vue 2 / Options-API-only consumers. Vue 3.3+ Composition API is the contract. Vue 2 has reached end-of-life; we are not back-porting. (Note: Options API components inside a Vue 3 app are supported — the boundary catches errors from both authoring styles. The parity test suite pins this contract.)
  • Vuex state snapshot on error. Pinia is the supported store integration via installPiniaIntegration. Vuex consumers can mirror the same shape with sdk.setContext('vuex', ...) from a custom plugin, but we don't ship one.

License

Apache-2.0. See the repo root LICENSE and the package NOTICE.