@sentry/wizard
Version:
Sentry wizard helping you to configure your project
216 lines (215 loc) • 9.71 kB
JavaScript
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
;