@oopsie-exceptions/nextjs
v0.1.4
Published
Next.js App Router bindings for @oopsie-exceptions: instrumentation hooks, client component, GlobalErrorReporter, server-action and route-handler wrappers.
Downloads
145
Maintainers
Readme
@oopsie-exceptions/nextjs
Next.js App Router bindings for @oopsie-exceptions. Modeled on Sentry's sentry.{client,server}.config.ts pattern.
Install
npm install @oopsie-exceptions/core @oopsie-exceptions/node @oopsie-exceptions/browser @oopsie-exceptions/nextjsQuickstart
1. Two config files at your project root
// oopsie.client.config.ts
import type { ClientConfig } from "@oopsie-exceptions/core";
import { BrowserTransport, browserServerInfo } from "@oopsie-exceptions/browser";
const config: ClientConfig = {
appName: "my-app",
environment: process.env.NEXT_PUBLIC_VERCEL_ENV ?? "development",
webhooks: [{
url: "https://oopsie.example.com/api/v1/exceptions",
headers: { Authorization: "Bearer pk_write_only_token_abc123..." },
}],
transport: new BrowserTransport(),
serverInfo: browserServerInfo,
};
export default config;// oopsie.server.config.ts
import type { ClientConfig } from "@oopsie-exceptions/core";
import { NodeTransport, AsyncLocalStorageContextStore, nodeServerInfo } from "@oopsie-exceptions/node";
const config: ClientConfig = {
appName: "my-app",
environment: process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? "development",
webhooks: [{
url: "https://oopsie.example.com/api/v1/exceptions",
headers: { Authorization: `Bearer ${process.env.OOPSIE_SERVER_TOKEN}` },
}],
transport: new NodeTransport(),
contextStore: new AsyncLocalStorageContextStore(),
serverInfo: nodeServerInfo,
};
export default config;2. instrumentation.ts
import config from "./oopsie.server.config";
import { configureServer, onRequestError } from "@oopsie-exceptions/nextjs/instrumentation";
export function register() {
configureServer(config);
}
export { onRequestError };3. Browser bootstrap (Sentry-style "use client" wrapper)
// app/oopsie-bootstrap.tsx
"use client";
import { configureClient } from "@oopsie-exceptions/nextjs";
import { installGlobalHandlers } from "@oopsie-exceptions/browser";
import { useEffect, useRef } from "react";
import oopsieConfig from "../oopsie.client.config";
export function OopsieBootstrap() {
const didInit = useRef(false);
useEffect(() => {
if (didInit.current) return;
didInit.current = true;
const client = configureClient(oopsieConfig);
const uninstall = installGlobalHandlers(client);
return () => { uninstall(); };
}, []);
return null;
}// app/layout.tsx (server component)
import { OopsieBootstrap } from "./oopsie-bootstrap";
// ...
<OopsieBootstrap />4. app/global-error.tsx
"use client";
import { GlobalErrorReporter } from "@oopsie-exceptions/nextjs/global-error";
export default function GlobalError({ error, reset }) {
return <GlobalErrorReporter error={error} reset={reset} />;
}Manual capture
// Server-side (route handler, server action, API, middleware):
import { captureException } from "@oopsie-exceptions/nextjs/instrumentation";
// Client component:
import { captureException } from "@oopsie-exceptions/nextjs";wrapServerAction / wrapRouteHandler wrap a function so thrown errors are reported + re-thrown:
import { wrapServerAction, wrapRouteHandler } from "@oopsie-exceptions/nextjs";
export const createPost = wrapServerAction(async (data) => { /* ... */ });
export const GET = wrapRouteHandler(async (req) => { /* ... */ });See the root README for full API docs.
