UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

216 lines (215 loc) 9.71 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.addVitePluginToConfig = exports.configureVitePlugin = void 0; // @ts-expect-error - clack is ESM and TS complains about that. It works though const clack = __importStar(require("@clack/prompts")); // @ts-expect-error - magicast is ESM and TS complains about that. It works though const magicast_1 = require("magicast"); // @ts-expect-error - magicast is ESM and TS complains about that. It works though const helpers_1 = require("magicast/helpers"); const recast = __importStar(require("recast")); const Sentry = __importStar(require("@sentry/node")); const chalk_1 = __importDefault(require("chalk")); const clack_1 = require("../../utils/clack"); const package_json_1 = require("../../utils/package-json"); const ast_utils_1 = require("../../utils/ast-utils"); const path = __importStar(require("path")); const fs = __importStar(require("fs")); const debug_1 = require("../../utils/debug"); const getViteConfigSnippet = (options, colors) => (0, clack_1.makeCodeSnippet)(colors, (unchanged, plus, _) => unchanged(`import { defineConfig } from "vite"; ${plus('import { sentryVitePlugin } from "@sentry/vite-plugin";')} export default defineConfig({ build: { ${plus('sourcemap: true, // Source map generation must be turned on')} }, plugins: [ // Put the Sentry vite plugin after all other plugins ${plus(`sentryVitePlugin({ authToken: process.env.SENTRY_AUTH_TOKEN, org: "${options.orgSlug}", project: "${options.projectSlug}",${options.selfHosted ? `\n url: "${options.url}",` : ''} }),`)} ], });`)); const configureVitePlugin = async (options) => { await (0, clack_1.installPackage)({ packageName: '@sentry/vite-plugin', alreadyInstalled: (0, package_json_1.hasPackageInstalled)('@sentry/vite-plugin', await (0, clack_1.getPackageDotJson)()), }); const viteConfigPath = (0, ast_utils_1.findFile)(path.resolve(process.cwd(), 'vite.config')) ?? (await (0, clack_1.askForToolConfigPath)('Vite', 'vite.config.js')); let successfullyAdded = false; if (viteConfigPath) { successfullyAdded = await addVitePluginToConfig(viteConfigPath, options); } else { successfullyAdded = await (0, clack_1.createNewConfigFile)(path.join(process.cwd(), 'vite.config.js'), getViteConfigSnippet(options, false), 'More information about vite configs: https://vitejs.dev/config/'); Sentry.setTag('created-new-config', successfullyAdded ? 'success' : 'fail'); } if (successfullyAdded) { clack.log.info(`We recommend checking the ${viteConfigPath ? 'modified' : 'added'} file after the wizard finished to ensure it works with your build setup.`); Sentry.setTag('ast-mod', 'success'); } else { Sentry.setTag('ast-mod', 'fail'); await (0, clack_1.showCopyPasteInstructions)({ filename: path.basename(viteConfigPath || 'vite.config.js'), codeSnippet: getViteConfigSnippet(options, true), }); } await (0, clack_1.addDotEnvSentryBuildPluginFile)(options.authToken); }; exports.configureVitePlugin = configureVitePlugin; async function addVitePluginToConfig(viteConfigPath, options) { try { const prettyViteConfigFilename = chalk_1.default.cyan(path.basename(viteConfigPath)); const viteConfigContent = (await fs.promises.readFile(viteConfigPath)).toString(); const mod = (0, magicast_1.parseModule)(viteConfigContent); if ((0, ast_utils_1.hasSentryContent)(mod.$ast)) { const shouldContinue = await (0, clack_1.abortIfCancelled)(clack.select({ message: `${prettyViteConfigFilename} already contains Sentry-related code. Should the wizard modify it anyway?`, options: [ { label: 'Yes, add the Sentry Vite plugin', value: true, }, { label: 'No, show me instructions to manually add the plugin', value: false, }, ], initialValue: true, })); if (!shouldContinue) { Sentry.setTag('ast-mod-fail-reason', 'has-sentry-content'); return false; } } const enabledSourcemaps = enableSourcemapGeneration(mod.$ast); if (!enabledSourcemaps) { Sentry.setTag('ast-mod-fail-reason', 'insertion-fail'); return false; } const { orgSlug: org, projectSlug: project, selfHosted, url } = options; (0, helpers_1.addVitePlugin)(mod, { imported: 'sentryVitePlugin', from: '@sentry/vite-plugin', constructor: 'sentryVitePlugin', options: { org, project, ...(selfHosted && { url }), }, }); const code = (0, magicast_1.generateCode)(mod.$ast).code; await fs.promises.writeFile(viteConfigPath, code); clack.log.success(`Added the Sentry Vite plugin to ${prettyViteConfigFilename} and enabled source maps`); return true; } catch (e) { (0, debug_1.debug)(e); Sentry.setTag('ast-mod-fail-reason', 'insertion-fail'); return false; } } exports.addVitePluginToConfig = addVitePluginToConfig; function enableSourcemapGeneration(program) { const configObj = getViteConfigObject(program); if (!configObj) { return false; } const b = recast.types.builders; const buildProp = configObj.properties.find((p) => p.key.type === 'Identifier' && p.key.name === 'build'); // case 1: build property doesn't exist yet, so we can just add it if (!buildProp) { configObj.properties.push(b.objectProperty(b.identifier('build'), b.objectExpression([ b.objectProperty(b.identifier('sourcemap'), b.booleanLiteral(true)), ]))); return true; } const isValidBuildProp = buildProp.type === 'ObjectProperty' && buildProp.value.type === 'ObjectExpression'; if (!isValidBuildProp) { return false; } const sourceMapsProp = buildProp.value.type === 'ObjectExpression' && buildProp.value.properties.find((p) => p.key.type === 'Identifier' && p.key.name === 'sourcemap'); // case 2: build.sourcemap property doesn't exist yet, so we just add it if (!sourceMapsProp && buildProp.value.type === 'ObjectExpression') { buildProp.value.properties.push(b.objectProperty(b.identifier('sourcemap'), b.booleanLiteral(true))); return true; } if (!sourceMapsProp || sourceMapsProp.type !== 'ObjectProperty') { return false; } // case 3: build.sourcemap property exists, and it's set to 'hidden' if (sourceMapsProp.value.type === 'StringLiteral' && sourceMapsProp.value.value === 'hidden') { // nothing to do for us return true; } // case 4: build.sourcemap property exists, but it's not enabled, so we set it to true // or it is already true in which case this is a noop sourceMapsProp.value = b.booleanLiteral(true); return true; } function getViteConfigObject(program) { const defaultExport = program.body.find((s) => s.type === 'ExportDefaultDeclaration'); if (!defaultExport) { return undefined; } if (defaultExport.declaration.type === 'ObjectExpression') { return defaultExport.declaration; } if (defaultExport.declaration.type === 'CallExpression' && defaultExport.declaration.arguments[0].type === 'ObjectExpression') { return defaultExport.declaration.arguments[0]; } if (defaultExport.declaration.type === 'Identifier') { const configId = defaultExport.declaration.name; return findConfigNode(configId, program); } return undefined; } function findConfigNode(configId, program) { for (const node of program.body) { if (node.type === 'VariableDeclaration') { for (const declaration of node.declarations) { if (declaration.type === 'VariableDeclarator' && declaration.id.type === 'Identifier' && declaration.id.name === configId && declaration.init?.type === 'ObjectExpression') { return declaration.init; } } } } return undefined; } //# sourceMappingURL=vite.js.map