@evinvest/error-monitoring
v0.1.0
Published
Vendor-neutral error-monitoring toolkit: a tiny injectable ErrorSink core plus Sentry adapters for React, Node/Edge, and Next.js. Mirrors the error_monitoring Cargo feature.
Readme
@evinvest/error-monitoring
A vendor-neutral error-monitoring toolkit — the TypeScript mirror of the
error_monitoring feature of the ev Rust
crate. The core is a tiny injectable ErrorSink port
that imports no monitoring SDK; concrete Sentry
adapters for React, Node/Edge, and Next.js live behind separate subpath exports
so you pay only for what you import.
Dep-honesty. The package declares zero runtime
dependencies. The Sentry SDKs (@sentry/react,@sentry/node,@sentry/nextjs),next, andreactare all optionalpeerDependencies— install only the ones the subpaths you use require. The.core needs none of them.
Install
Published to the public npm registry:
npm i @evinvest/error-monitoring
# plus the peers for the subpaths you use, e.g.:
npm i @sentry/react react # for ./react
npm i @sentry/node # for ./node
npm i @sentry/nextjs next react # for ./next (+ ./react provider)Requires Node ≥ 20. dist/ is built on publish, not committed.
Subpaths & quick start
. — vendor-neutral core
Server-safe, no SDK. The seam your app code depends on.
import { createSentrySink, noopErrorSink, defaultTracesSampleRate } from "@evinvest/error-monitoring";
import type { ErrorSink, SentryInitOptions } from "@evinvest/error-monitoring";
import * as Sentry from "@sentry/node";
const sink: ErrorSink = process.env.SENTRY_DSN
? createSentrySink(Sentry) // reportError(err, ctx) → captureException(err, { extra: ctx })
: noopErrorSink();
sink.reportError(new Error("boom"), { feature: "checkout" });./react — client provider + boundary ("use client")
import { ErrorMonitoringProvider, ErrorBoundary } from "@evinvest/error-monitoring/react";
import * as Sentry from "@sentry/react";
// Mount once near the root — boots browser Sentry (DSN ← NEXT_PUBLIC_SENTRY_DSN).
<ErrorMonitoringProvider>
<ErrorBoundary sentry={Sentry} fallback={(error, reset) => (
<div role="alert"><p>{error.message}</p><button onClick={reset}>Retry</button></div>
)}>
<App />
</ErrorBoundary>
</ErrorMonitoringProvider>ErrorBoundary is decoupled from any design system: no @evinvest/uikit, no
lucide-react, no Tailwind. Bring your own fallback UI.
./node — server / edge init
import { initServer, initEdge } from "@evinvest/error-monitoring/node";
await initServer({}); // dsn ← SENTRY_DSN, tracesSampleRate 0.1 prod / 1.0 else
await initEdge({}); // dsn ← SENTRY_DSN, tracesSampleRate 0 (edge)./next — build/server wiring (no banner)
// instrumentation.ts
import { register, captureRequestError } from "@evinvest/error-monitoring/next";
export { register };
export const onRequestError = captureRequestError;
// next.config.ts
import { withSentry } from "@evinvest/error-monitoring/next";
export default await withSentry({ reactStrictMode: true }, { /* org, project, … */ });See GUIDE.md for the full Next.js cookbook.
Rust ↔ TS parity
The Rust crate is the source of truth; this package preserves its semantics while reading like idiomatic TS. The load-bearing mapping is the report seam:
| Concept | meaning |
| --- | --- |
| reportError(err, ctx) | Sentry.captureException(err, ctx ? { extra: ctx } : undefined) |
| ErrorSink | the vendor-neutral port; vendor injected via createSentrySink |
| client tracesSampleRate | 0.1 in production, 1.0 elsewhere |
| edge tracesSampleRate | 0 (tracing disabled) |
| replays | replaysOnErrorSampleRate: 1.0, replaysSessionSampleRate: 0.05, browser-only |
Env-var conventions: browser NEXT_PUBLIC_SENTRY_DSN / NEXT_PUBLIC_APP_ENV;
server & edge SENTRY_DSN / APP_ENV; both default environment to
"development".
Limitations
- Sentry-shaped, not multi-vendor out of the box. The core is vendor-neutral
(
ErrorSink+ structuralSentryLike), but the bundled adapters target the Sentry SDKs. To use another backend, implementErrorSinkyourself — the adapters are thin enough to copy. - Replay & browser integrations are added only client-side
(
typeof window !== "undefined"); they never run on the server. - Source maps are uploaded by
withSentryonly when the build-time env vars (SENTRY_AUTH_TOKEN,SENTRY_ORG,SENTRY_PROJECT) are set; otherwise stack traces stay minified. SeeGUIDE.mdgotchas. - No-op without a DSN. Every
initis a no-op when its DSN env var is unset, so local dev works with no configuration.
Develop
npm i
npm run typecheck # tsc --noEmit + tsc -p tsconfig.core.json --noEmit (no-DOM core)
npm run test # vitest (node + jsdom projects, split by file suffix)
npm run build # tsup → dist/ (ESM + d.ts); only ./react carries "use client"The Rust counterpart is verified from the repo root:
cargo test -p ev --features error_monitoring
cargo clippy -p ev --features error_monitoring --all-targets -- -D warnings