UNPKG

@critters/next

Version:

Secure bug reporting library for Next.js applications

153 lines (152 loc) 6.78 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.withErrorReporting = withErrorReporting; exports.withPageErrorReporting = withPageErrorReporting; exports.withAppErrorReporting = withAppErrorReporting; const reporter_1 = require("./reporter"); const react_1 = __importDefault(require("react")); /** * Create a middleware for Next.js API routes to catch and report errors * @param handler The Next.js API route handler * @param options Additional options for error reporting * @returns A wrapped handler that reports errors */ function withErrorReporting(handler, options = {}) { return (req, res) => __awaiter(this, void 0, void 0, function* () { try { // Call the original handler return yield handler(req, res); } catch (error) { // Prepare metadata for error reporting const metadata = { route: req.url, method: req.method, }; // Capture request data if enabled if (options.captureRequest) { metadata.query = req.query; metadata.body = req.body; metadata.headers = req.headers; metadata.cookies = req.cookies; } // Report the error yield reporter_1.Critters.getInstance().catch(error, metadata); // Call the onError callback if provided if (options.onError && error instanceof Error) { options.onError(error, req, res); } // Re-throw the error to be handled by Next.js throw error; } }); } /** * Create a middleware for Next.js pages to catch and report errors * @param options Additional options for error reporting * @returns A higher-order component that wraps the page component */ function withPageErrorReporting(options = {}) { return function withErrorReportingHOC(PageComponent) { // Define a new component that wraps the page component const WrappedComponent = (props) => { return react_1.default.createElement(PageComponent, props); }; // Copy static methods and display name WrappedComponent.displayName = `withErrorReporting(${PageComponent.displayName || PageComponent.name || "Page"})`; // Handle getInitialProps if it exists if ("getInitialProps" in PageComponent) { WrappedComponent.getInitialProps = (ctx) => __awaiter(this, void 0, void 0, function* () { try { // Call the original getInitialProps const initialProps = yield PageComponent.getInitialProps(ctx); return initialProps; } catch (error) { // Prepare metadata for error reporting const metadata = { page: ctx.pathname, asPath: ctx.asPath, query: ctx.query, }; // Capture initial props context if enabled if (options.captureInitialProps) { metadata.initialPropsContext = { req: ctx.req ? { url: ctx.req.url, method: ctx.req.method, headers: ctx.req.headers, } : undefined, res: ctx.res ? { statusCode: ctx.res.statusCode, } : undefined, }; } // Report the error yield reporter_1.Critters.getInstance().catch(error, metadata); // Call the onError callback if provided if (options.onError && error instanceof Error) { options.onError(error, ctx); } // Re-throw the error throw error; } }); } return WrappedComponent; }; } /** * Create a middleware for Next.js App Router to catch and report errors * @param options Additional options for error reporting * @returns A higher-order component that wraps the page component */ function withAppErrorReporting(options = {}) { return function withAppErrorReportingHOC(AppComponent) { // Define a new component that wraps the app component function WrappedComponent(props) { try { return react_1.default.createElement(AppComponent, props); } catch (error) { // Prepare metadata for error reporting const metadata = {}; // Capture params if enabled if (options.captureParams && props.params) { metadata.params = props.params; } // Capture search params if enabled if (options.captureSearchParams && props.searchParams) { metadata.searchParams = props.searchParams; } // Report the error reporter_1.Critters.getInstance().catch(error, metadata); // Call the onError callback if provided if (options.onError && error instanceof Error) { options.onError(error, props); } // Re-throw the error to be handled by Next.js throw error; } } // Copy display name WrappedComponent.displayName = `withAppErrorReporting(${AppComponent.displayName || AppComponent.name || "AppComponent"})`; return WrappedComponent; }; }