@sentry/wizard
Version:
Sentry wizard helping you to configure your project
298 lines • 15.6 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
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 __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 __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
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-ignore - clack is ESM and TS complains about that. It works though
var clack = __importStar(require("@clack/prompts"));
// @ts-ignore - magicast is ESM and TS complains about that. It works though
var magicast_1 = require("magicast");
// @ts-ignore - magicast is ESM and TS complains about that. It works though
var helpers_1 = require("magicast/helpers");
var recast = __importStar(require("recast"));
var Sentry = __importStar(require("@sentry/node"));
var chalk_1 = __importDefault(require("chalk"));
var clack_utils_1 = require("../../utils/clack-utils");
var package_json_1 = require("../../utils/package-json");
var ast_utils_1 = require("../../utils/ast-utils");
var path = __importStar(require("path"));
var fs = __importStar(require("fs"));
var debug_1 = require("../../utils/debug");
var getViteConfigSnippet = function (options, colors) {
return (0, clack_utils_1.makeCodeSnippet)(colors, function (unchanged, plus, _) {
return unchanged("import { defineConfig } from \"vite\";\n".concat(plus('import { sentryVitePlugin } from "@sentry/vite-plugin";'), "\n\nexport default defineConfig({\n build: {\n ").concat(plus('sourcemap: true, // Source map generation must be turned on'), "\n },\n plugins: [\n // Put the Sentry vite plugin after all other plugins\n ").concat(plus("sentryVitePlugin({\n authToken: process.env.SENTRY_AUTH_TOKEN,\n org: \"".concat(options.orgSlug, "\",\n project: \"").concat(options.projectSlug, "\",").concat(options.selfHosted ? "\n url: \"".concat(options.url, "\",") : '', "\n }),")), "\n ],\n});"));
});
};
var configureVitePlugin = function (options) { return __awaiter(void 0, void 0, void 0, function () {
var _a, _b, _c, viteConfigPath, _d, successfullyAdded;
var _e;
var _f;
return __generator(this, function (_g) {
switch (_g.label) {
case 0:
_a = clack_utils_1.installPackage;
_e = {
packageName: '@sentry/vite-plugin'
};
_b = package_json_1.hasPackageInstalled;
_c = ['@sentry/vite-plugin'];
return [4 /*yield*/, (0, clack_utils_1.getPackageDotJson)()];
case 1: return [4 /*yield*/, _a.apply(void 0, [(_e.alreadyInstalled = _b.apply(void 0, _c.concat([_g.sent()])),
_e)])];
case 2:
_g.sent();
if (!((_f = (0, ast_utils_1.findFile)(path.resolve(process.cwd(), 'vite.config'))) !== null && _f !== void 0)) return [3 /*break*/, 3];
_d = _f;
return [3 /*break*/, 5];
case 3: return [4 /*yield*/, (0, clack_utils_1.askForToolConfigPath)('Vite', 'vite.config.js')];
case 4:
_d = (_g.sent());
_g.label = 5;
case 5:
viteConfigPath = _d;
successfullyAdded = false;
if (!viteConfigPath) return [3 /*break*/, 7];
return [4 /*yield*/, addVitePluginToConfig(viteConfigPath, options)];
case 6:
successfullyAdded = _g.sent();
return [3 /*break*/, 9];
case 7: return [4 /*yield*/, (0, clack_utils_1.createNewConfigFile)(path.join(process.cwd(), 'vite.config.js'), getViteConfigSnippet(options, false), 'More information about vite configs: https://vitejs.dev/config/')];
case 8:
successfullyAdded = _g.sent();
Sentry.setTag('created-new-config', successfullyAdded ? 'success' : 'fail');
_g.label = 9;
case 9:
if (!successfullyAdded) return [3 /*break*/, 10];
clack.log.info("We recommend checking the ".concat(viteConfigPath ? 'modified' : 'added', " file after the wizard finished to ensure it works with your build setup."));
Sentry.setTag('ast-mod', 'success');
return [3 /*break*/, 12];
case 10:
Sentry.setTag('ast-mod', 'fail');
return [4 /*yield*/, (0, clack_utils_1.showCopyPasteInstructions)(path.basename(viteConfigPath || 'vite.config.js'), getViteConfigSnippet(options, true))];
case 11:
_g.sent();
_g.label = 12;
case 12: return [4 /*yield*/, (0, clack_utils_1.addDotEnvSentryBuildPluginFile)(options.authToken)];
case 13:
_g.sent();
return [2 /*return*/];
}
});
}); };
exports.configureVitePlugin = configureVitePlugin;
function addVitePluginToConfig(viteConfigPath, options) {
return __awaiter(this, void 0, void 0, function () {
var prettyViteConfigFilename, viteConfigContent, mod, shouldContinue, enabledSourcemaps, org, project, selfHosted, url, code, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 5, , 6]);
prettyViteConfigFilename = chalk_1.default.cyan(path.basename(viteConfigPath));
return [4 /*yield*/, fs.promises.readFile(viteConfigPath)];
case 1:
viteConfigContent = (_a.sent()).toString();
mod = (0, magicast_1.parseModule)(viteConfigContent);
if (!(0, ast_utils_1.hasSentryContent)(mod.$ast)) return [3 /*break*/, 3];
return [4 /*yield*/, (0, clack_utils_1.abortIfCancelled)(clack.select({
message: "".concat(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,
}))];
case 2:
shouldContinue = _a.sent();
if (!shouldContinue) {
Sentry.setTag('ast-mod-fail-reason', 'has-sentry-content');
return [2 /*return*/, false];
}
_a.label = 3;
case 3:
enabledSourcemaps = enableSourcemapGeneration(mod.$ast);
if (!enabledSourcemaps) {
Sentry.setTag('ast-mod-fail-reason', 'insertion-fail');
return [2 /*return*/, false];
}
org = options.orgSlug, project = options.projectSlug, selfHosted = options.selfHosted, url = options.url;
(0, helpers_1.addVitePlugin)(mod, {
imported: 'sentryVitePlugin',
from: '@sentry/vite-plugin',
constructor: 'sentryVitePlugin',
options: __assign({ org: org, project: project }, (selfHosted && { url: url })),
});
code = (0, magicast_1.generateCode)(mod.$ast).code;
return [4 /*yield*/, fs.promises.writeFile(viteConfigPath, code)];
case 4:
_a.sent();
clack.log.success("Added the Sentry Vite plugin to ".concat(prettyViteConfigFilename, " and enabled source maps"));
return [2 /*return*/, true];
case 5:
e_1 = _a.sent();
(0, debug_1.debug)(e_1);
Sentry.setTag('ast-mod-fail-reason', 'insertion-fail');
return [2 /*return*/, false];
case 6: return [2 /*return*/];
}
});
});
}
exports.addVitePluginToConfig = addVitePluginToConfig;
function enableSourcemapGeneration(program) {
var configObj = getViteConfigObject(program);
if (!configObj) {
return false;
}
var b = recast.types.builders;
var buildProp = configObj.properties.find(function (p) {
return 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;
}
var isValidBuildProp = buildProp.type === 'ObjectProperty' &&
buildProp.value.type === 'ObjectExpression';
if (!isValidBuildProp) {
return false;
}
var sourceMapsProp = buildProp.value.type === 'ObjectExpression' &&
buildProp.value.properties.find(function (p) {
return 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) {
var defaultExport = program.body.find(function (s) { return 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') {
var configId = defaultExport.declaration.name;
return findConfigNode(configId, program);
}
return undefined;
}
function findConfigNode(configId, program) {
var _a;
for (var _i = 0, _b = program.body; _i < _b.length; _i++) {
var node = _b[_i];
if (node.type === 'VariableDeclaration') {
for (var _c = 0, _d = node.declarations; _c < _d.length; _c++) {
var declaration = _d[_c];
if (declaration.type === 'VariableDeclarator' &&
declaration.id.type === 'Identifier' &&
declaration.id.name === configId &&
((_a = declaration.init) === null || _a === void 0 ? void 0 : _a.type) === 'ObjectExpression') {
return declaration.init;
}
}
}
}
return undefined;
}
//# sourceMappingURL=vite.js.map