UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

171 lines 7.36 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.instrumentRoot = void 0; /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ const recast = __importStar(require("recast")); const path = __importStar(require("path")); const magicast_1 = require("magicast"); const templates_1 = require("../templates"); const ast_utils_1 = require("../../utils/ast-utils"); const debug_1 = require("../../utils/debug"); function hasCaptureExceptionCall(node) { let found = false; recast.visit(node, { visitCallExpression(path) { const callee = path.value.callee; if ((callee.type === 'MemberExpression' && callee.object?.name === 'Sentry' && callee.property?.name === 'captureException') || (callee.type === 'Identifier' && callee.name === 'captureException')) { found = true; } this.traverse(path); }, }); return found; } function addCaptureExceptionCall(functionNode) { const captureExceptionCall = recast.parse(`Sentry.captureException(error);`) .program.body[0]; const functionBody = (0, ast_utils_1.safeGetFunctionBody)(functionNode); if (functionBody) { if (!(0, ast_utils_1.safeInsertBeforeReturn)(functionBody, captureExceptionCall)) { functionBody.push(captureExceptionCall); } } else { (0, debug_1.debug)('Could not safely access ErrorBoundary function body'); } } function findErrorBoundaryInExports(namedExports) { return namedExports.some((namedExport) => { const declaration = namedExport.declaration; if (!declaration) { return namedExport.specifiers?.some((spec) => spec.type === 'ExportSpecifier' && spec.exported?.type === 'Identifier' && spec.exported.name === 'ErrorBoundary'); } if (declaration.type === 'FunctionDeclaration') { return declaration.id?.name === 'ErrorBoundary'; } if (declaration.type === 'VariableDeclaration') { return declaration.declarations.some((decl) => { // @ts-expect-error - id should always have a name in this case return decl.id?.name === 'ErrorBoundary'; }); } return false; }); } async function instrumentRoot(rootFileName) { const filePath = path.join(process.cwd(), 'app', rootFileName); const rootRouteAst = await (0, magicast_1.loadFile)(filePath); const exportsAst = rootRouteAst.exports.$ast; const namedExports = exportsAst.body.filter((node) => node.type === 'ExportNamedDeclaration'); const foundErrorBoundary = findErrorBoundaryInExports(namedExports); const alreadyHasSentry = (0, ast_utils_1.hasSentryContent)(rootRouteAst.$ast); if (!alreadyHasSentry) { rootRouteAst.imports.$add({ from: '@sentry/react-router', imported: '*', local: 'Sentry', }); } if (!foundErrorBoundary) { const hasIsRouteErrorResponseImport = rootRouteAst.imports.$items.some((item) => item.imported === 'isRouteErrorResponse' && item.from === 'react-router'); if (!hasIsRouteErrorResponseImport) { rootRouteAst.imports.$add({ from: 'react-router', imported: 'isRouteErrorResponse', local: 'isRouteErrorResponse', }); } recast.visit(rootRouteAst.$ast, { visitExportDefaultDeclaration(path) { const implementation = recast.parse(templates_1.ERROR_BOUNDARY_TEMPLATE).program .body[0]; path.insertBefore(recast.types.builders.exportDeclaration(false, implementation)); this.traverse(path); }, }); } else { recast.visit(rootRouteAst.$ast, { visitExportNamedDeclaration(path) { const declaration = path.value.declaration; if (!declaration) { this.traverse(path); return; } let functionToInstrument = null; if (declaration.type === 'FunctionDeclaration' && declaration.id?.name === 'ErrorBoundary') { functionToInstrument = declaration; } else if (declaration.type === 'VariableDeclaration' && declaration.declarations?.[0]?.id?.name === 'ErrorBoundary') { const init = declaration.declarations[0].init; if (init && (init.type === 'FunctionExpression' || init.type === 'ArrowFunctionExpression')) { functionToInstrument = init; } } if (functionToInstrument && !hasCaptureExceptionCall(functionToInstrument)) { addCaptureExceptionCall(functionToInstrument); } this.traverse(path); }, visitVariableDeclaration(path) { if (path.value.declarations?.[0]?.id?.name === 'ErrorBoundary') { const init = path.value.declarations[0].init; if (init && (init.type === 'FunctionExpression' || init.type === 'ArrowFunctionExpression') && !hasCaptureExceptionCall(init)) { addCaptureExceptionCall(init); } } this.traverse(path); }, visitFunctionDeclaration(path) { if (path.value.id?.name === 'ErrorBoundary' && !hasCaptureExceptionCall(path.value)) { addCaptureExceptionCall(path.value); } this.traverse(path); }, }); } await (0, magicast_1.writeFile)(rootRouteAst.$ast, filePath); } exports.instrumentRoot = instrumentRoot; //# sourceMappingURL=root.js.map