UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

169 lines 7.26 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; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.instrumentViteConfig = exports.addReactRouterPluginToViteConfig = void 0; const recast = __importStar(require("recast")); const path = __importStar(require("path")); const fs = __importStar(require("fs")); // @ts-expect-error - magicast is ESM and TS complains about that. It works though const magicast_1 = require("magicast"); // @ts-expect-error - clack is ESM and TS complains about that. It works though const prompts_1 = __importDefault(require("@clack/prompts")); const chalk_1 = __importDefault(require("chalk")); const ast_utils_1 = require("../../utils/ast-utils"); /** * Extracts ObjectExpression from function body. * Handles both arrow functions with object returns and block statements with explicit returns. * * - Arrow with object-return: (config) => ({ ... }) * - Arrow with block: (config) => { return { ... }; } * - Function with block: function(config) { return { ... }; } * * @param body - The function body to extract from * @returns The ObjectExpression if found, undefined otherwise */ function extractFromFunctionBody(body) { if (body.type === 'ObjectExpression') { return body; } if (body.type === 'BlockStatement') { const blockBody = body; const returnStatement = blockBody.body.find((stmt) => stmt.type === 'ReturnStatement'); return returnStatement?.argument?.type === 'ObjectExpression' ? returnStatement.argument : undefined; } return undefined; } /** * Creates the sentryReactRouter Vite plugin call expression. * * Generates AST for: * sentryReactRouter({ * org: "...", * project: "...", * authToken: process.env.SENTRY_AUTH_TOKEN * }, config) * * @param orgSlug - Sentry organization slug * @param projectSlug - Sentry project slug * @returns CallExpression node for the Sentry Vite plugin */ function createSentryPluginCall(orgSlug, projectSlug) { const b = recast.types.builders; return b.callExpression(b.identifier('sentryReactRouter'), [ b.objectExpression([ b.objectProperty(b.identifier('org'), b.stringLiteral(orgSlug)), b.objectProperty(b.identifier('project'), b.stringLiteral(projectSlug)), b.objectProperty(b.identifier('authToken'), b.memberExpression(b.memberExpression(b.identifier('process'), b.identifier('env')), b.identifier('SENTRY_AUTH_TOKEN'))), ]), b.identifier('config'), ]); } function addReactRouterPluginToViteConfig(program, orgSlug, projectSlug) { const b = recast.types.builders; let wasConverted = false; const defaultExport = program.body.find((node) => node.type === 'ExportDefaultDeclaration'); if (!defaultExport) { return { success: false, wasConverted: false }; } let configObj; let defineConfigCall; if (defaultExport.declaration.type === 'CallExpression' && defaultExport.declaration.callee.type === 'Identifier' && defaultExport.declaration.callee.name === 'defineConfig') { defineConfigCall = defaultExport.declaration; // Early exit if not single argument if (defineConfigCall.arguments.length !== 1) { return { success: false, wasConverted: false }; } const arg = defineConfigCall.arguments[0]; if (arg.type === 'ObjectExpression') { configObj = arg; // Convert to function form const arrowFunction = b.arrowFunctionExpression([b.identifier('config')], configObj); defineConfigCall.arguments[0] = arrowFunction; wasConverted = true; } else if (arg.type === 'ArrowFunctionExpression' || arg.type === 'FunctionExpression') { configObj = extractFromFunctionBody(arg.body); } } if (!configObj) { return { success: false, wasConverted }; } const pluginsProp = (0, ast_utils_1.findProperty)(configObj, 'plugins'); const sentryPluginCall = createSentryPluginCall(orgSlug, projectSlug); if (!pluginsProp) { configObj.properties.push(b.objectProperty(b.identifier('plugins'), b.arrayExpression([sentryPluginCall]))); } else if (pluginsProp.value.type === 'ArrayExpression' && pluginsProp.type === 'ObjectProperty') { const arrayExpr = pluginsProp.value; // Defensive: ensure elements array exists if (!arrayExpr.elements) { arrayExpr.elements = []; } arrayExpr.elements.push(sentryPluginCall); } else { return { success: false, wasConverted }; } return { success: true, wasConverted }; } exports.addReactRouterPluginToViteConfig = addReactRouterPluginToViteConfig; async function instrumentViteConfig(orgSlug, projectSlug) { const configPath = fs.existsSync(path.join(process.cwd(), 'vite.config.ts')) ? path.join(process.cwd(), 'vite.config.ts') : path.join(process.cwd(), 'vite.config.js'); if (!fs.existsSync(configPath)) { throw new Error('Could not find vite.config.ts or vite.config.js'); } const configContent = await fs.promises.readFile(configPath, 'utf-8'); const filename = chalk_1.default.cyan(path.basename(configPath)); const mod = (0, magicast_1.parseModule)(configContent); if ((0, ast_utils_1.hasSentryContent)(mod.$ast)) { prompts_1.default.log.info(`${filename} already contains sentryReactRouter plugin.`); return { wasConverted: false }; } mod.imports.$add({ from: '@sentry/react-router', imported: 'sentryReactRouter', local: 'sentryReactRouter', }); const { success, wasConverted } = addReactRouterPluginToViteConfig(mod.$ast, orgSlug, projectSlug); if (!success) { throw new Error('Failed to modify Vite config structure'); } const code = (0, magicast_1.generateCode)(mod.$ast).code; await fs.promises.writeFile(configPath, code); return { wasConverted }; } exports.instrumentViteConfig = instrumentViteConfig; //# sourceMappingURL=vite.js.map