UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

619 lines 33.3 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 __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.hasPackageInstalled = exports.getPackageDotJson = exports.ensurePackageIsInstalled = exports.addDotEnvSentryBuildPluginFile = exports.addSentryCliRc = exports.askForSelfHosted = exports.installPackage = exports.askForProjectSelection = exports.askForWizardLogin = exports.confirmContinueEvenThoughNoGitRepo = exports.printWelcome = exports.abortIfCancelled = exports.abort = void 0; // @ts-ignore - clack is ESM and TS complains about that. It works though var clack = __importStar(require("@clack/prompts")); var axios_1 = __importDefault(require("axios")); var chalk_1 = __importDefault(require("chalk")); var childProcess = __importStar(require("child_process")); var fs = __importStar(require("fs")); var path = __importStar(require("path")); var timers_1 = require("timers"); var url_1 = require("url"); var util_1 = require("util"); var Sentry = __importStar(require("@sentry/node")); var clack_custom_select_1 = require("./vendor/clack-custom-select"); var SAAS_URL = 'https://sentry.io/'; function abort(message, status) { return __awaiter(this, void 0, void 0, function () { var sentryHub, sentryTransaction, sentrySession; return __generator(this, function (_a) { switch (_a.label) { case 0: clack.outro(message !== null && message !== void 0 ? message : 'Wizard setup cancelled.'); sentryHub = Sentry.getCurrentHub(); sentryTransaction = sentryHub.getScope().getTransaction(); sentryTransaction === null || sentryTransaction === void 0 ? void 0 : sentryTransaction.setStatus('aborted'); sentryTransaction === null || sentryTransaction === void 0 ? void 0 : sentryTransaction.finish(); sentrySession = sentryHub.getScope().getSession(); if (sentrySession) { sentrySession.status = status === 0 ? 'abnormal' : 'crashed'; sentryHub.captureSession(true); } return [4 /*yield*/, Sentry.flush(3000)]; case 1: _a.sent(); return [2 /*return*/, process.exit(status !== null && status !== void 0 ? status : 1)]; } }); }); } exports.abort = abort; function abortIfCancelled(input) { return __awaiter(this, void 0, void 0, function () { var _a, _b, sentryHub, sentryTransaction; return __generator(this, function (_c) { switch (_c.label) { case 0: _b = (_a = clack).isCancel; return [4 /*yield*/, input]; case 1: if (!_b.apply(_a, [_c.sent()])) return [3 /*break*/, 3]; clack.cancel('Wizard setup cancelled.'); sentryHub = Sentry.getCurrentHub(); sentryTransaction = sentryHub.getScope().getTransaction(); sentryTransaction === null || sentryTransaction === void 0 ? void 0 : sentryTransaction.setStatus('cancelled'); sentryTransaction === null || sentryTransaction === void 0 ? void 0 : sentryTransaction.finish(); sentryHub.captureSession(true); return [4 /*yield*/, Sentry.flush(3000)]; case 2: _c.sent(); process.exit(0); return [3 /*break*/, 4]; case 3: return [2 /*return*/, input]; case 4: return [2 /*return*/]; } }); }); } exports.abortIfCancelled = abortIfCancelled; function printWelcome(options) { var wizardPackage = {}; try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment wizardPackage = require(path.join(path.dirname(require.resolve('@sentry/wizard')), '..', 'package.json')); } catch (_a) { // We don't need to have this } // eslint-disable-next-line no-console console.log(''); clack.intro(chalk_1.default.inverse(" ".concat(options.wizardName, " "))); var welcomeText = options.message || 'This Wizard will help you to set up Sentry for your application.\nThank you for using Sentry :)'; if (options.promoCode) { welcomeText += "\n\nUsing promo-code: ".concat(options.promoCode); } if (wizardPackage.version) { welcomeText += "\n\nVersion: ".concat(wizardPackage.version); } clack.note(welcomeText); } exports.printWelcome = printWelcome; function confirmContinueEvenThoughNoGitRepo() { return __awaiter(this, void 0, void 0, function () { var _a, continueWithoutGit; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 1, , 5]); childProcess.execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore', }); return [3 /*break*/, 5]; case 1: _a = _b.sent(); return [4 /*yield*/, abortIfCancelled(clack.confirm({ message: 'You are not inside a git repository. The wizard will create and update files. Do you still want to continue?', }))]; case 2: continueWithoutGit = _b.sent(); Sentry.setTag('continue-without-git', continueWithoutGit); if (!!continueWithoutGit) return [3 /*break*/, 4]; return [4 /*yield*/, abort(undefined, 0)]; case 3: _b.sent(); _b.label = 4; case 4: return [3 /*break*/, 5]; case 5: return [2 /*return*/]; } }); }); } exports.confirmContinueEvenThoughNoGitRepo = confirmContinueEvenThoughNoGitRepo; function askForWizardLogin(options) { return __awaiter(this, void 0, void 0, function () { var hasSentryAccount, wizardHash, _a, loginUrl, loginSpinner, data; return __generator(this, function (_b) { switch (_b.label) { case 0: Sentry.setTag('has-promo-code', !!options.promoCode); return [4 /*yield*/, clack.confirm({ message: 'Do you already have a Sentry account?', })]; case 1: hasSentryAccount = _b.sent(); return [4 /*yield*/, abortIfCancelled(hasSentryAccount)]; case 2: hasSentryAccount = _b.sent(); Sentry.setTag('already-has-sentry-account', hasSentryAccount); _b.label = 3; case 3: _b.trys.push([3, 5, , 10]); return [4 /*yield*/, axios_1.default.get("".concat(options.url, "api/0/wizard/"))]; case 4: wizardHash = (_b.sent()).data.hash; return [3 /*break*/, 10]; case 5: _a = _b.sent(); if (!(options.url !== SAAS_URL)) return [3 /*break*/, 7]; clack.log.error('Loading Wizard failed. Did you provide the right URL?'); return [4 /*yield*/, abort(chalk_1.default.red('Please check your configuration and try again.\n\n Let us know if you think this is an issue with the wizard or Sentry: https://github.com/getsentry/sentry-wizard/issues'))]; case 6: _b.sent(); return [3 /*break*/, 9]; case 7: clack.log.error('Loading Wizard failed.'); return [4 /*yield*/, abort(chalk_1.default.red('Please try again in a few minutes and let us know if this issue persists: https://github.com/getsentry/sentry-wizard/issues'))]; case 8: _b.sent(); _b.label = 9; case 9: return [3 /*break*/, 10]; case 10: loginUrl = new url_1.URL("".concat(options.url, "account/settings/wizard/").concat(wizardHash, "/")); if (!hasSentryAccount) { loginUrl.searchParams.set('signup', '1'); if (options.platform) { loginUrl.searchParams.set('project_platform', options.platform); } } if (options.promoCode) { loginUrl.searchParams.set('code', options.promoCode); } clack.log.info("".concat(chalk_1.default.bold("Please open the following link in your browser to ".concat(hasSentryAccount ? 'log' : 'sign', " into Sentry:")), "\n\n").concat(chalk_1.default.cyan(loginUrl.toString()))); loginSpinner = clack.spinner(); loginSpinner.start('Waiting for you to click the link above 👆. Take your time.'); return [4 /*yield*/, new Promise(function (resolve) { var pollingInterval = (0, timers_1.setInterval)(function () { axios_1.default .get("".concat(options.url, "api/0/wizard/").concat(wizardHash, "/")) .then(function (result) { resolve(result.data); clearTimeout(timeout); clearInterval(pollingInterval); void axios_1.default.delete("".concat(options.url, "api/0/wizard/").concat(wizardHash, "/")); }) .catch(function () { // noop - just try again }); }, 500); var timeout = setTimeout(function () { clearInterval(pollingInterval); loginSpinner.stop('Login timed out. No worries - it happens to the best of us.'); Sentry.setTag('opened-wizard-link', false); void abort('Please restart the Wizard and log in to complete the setup.'); }, 180000); })]; case 11: data = _b.sent(); loginSpinner.stop('Login complete.'); Sentry.setTag('opened-wizard-link', true); return [2 /*return*/, data]; } }); }); } exports.askForWizardLogin = askForWizardLogin; function askForProjectSelection(projects) { return __awaiter(this, void 0, void 0, function () { var selection; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, abortIfCancelled((0, clack_custom_select_1.windowedSelect)({ maxItems: 12, message: 'Select your Sentry project.', options: projects.map(function (project) { return { value: project, label: "".concat(project.organization.slug, "/").concat(project.slug), }; }), }))]; case 1: selection = _a.sent(); Sentry.setTag('project', selection.slug); Sentry.setUser({ id: selection.organization.slug }); return [2 /*return*/, selection]; } }); }); } exports.askForProjectSelection = askForProjectSelection; function installPackage(_a) { var packageName = _a.packageName, alreadyInstalled = _a.alreadyInstalled; return __awaiter(this, void 0, void 0, function () { var shouldUpdatePackage, sdkInstallSpinner, packageManager, e_1; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!alreadyInstalled) return [3 /*break*/, 2]; return [4 /*yield*/, abortIfCancelled(clack.confirm({ message: "The ".concat(chalk_1.default.bold.cyan(packageName), " package is already installed. Do you want to update it to the latest version?"), }))]; case 1: shouldUpdatePackage = _b.sent(); if (!shouldUpdatePackage) { return [2 /*return*/]; } _b.label = 2; case 2: sdkInstallSpinner = clack.spinner(); return [4 /*yield*/, getPackageManager()]; case 3: packageManager = _b.sent(); sdkInstallSpinner.start("".concat(alreadyInstalled ? 'Updating' : 'Installing', " ").concat(chalk_1.default.bold.cyan(packageName), " with ").concat(chalk_1.default.bold(packageManager), ".")); _b.label = 4; case 4: _b.trys.push([4, 11, , 13]); if (!(packageManager === 'yarn')) return [3 /*break*/, 6]; return [4 /*yield*/, (0, util_1.promisify)(childProcess.exec)("yarn add ".concat(packageName, "@latest"))]; case 5: _b.sent(); return [3 /*break*/, 10]; case 6: if (!(packageManager === 'pnpm')) return [3 /*break*/, 8]; return [4 /*yield*/, (0, util_1.promisify)(childProcess.exec)("pnpm add ".concat(packageName, "@latest"))]; case 7: _b.sent(); return [3 /*break*/, 10]; case 8: if (!(packageManager === 'npm')) return [3 /*break*/, 10]; return [4 /*yield*/, (0, util_1.promisify)(childProcess.exec)("npm install ".concat(packageName, "@latest"))]; case 9: _b.sent(); _b.label = 10; case 10: return [3 /*break*/, 13]; case 11: e_1 = _b.sent(); sdkInstallSpinner.stop('Installation failed.'); clack.log.error("".concat(chalk_1.default.red('Encountered the following error during installation:'), "\n\n").concat(e_1, "\n\n").concat(chalk_1.default.dim('If you think this issue is caused by the Sentry wizard, let us know here:\nhttps://github.com/getsentry/sentry-wizard/issues'))); return [4 /*yield*/, abort()]; case 12: _b.sent(); return [3 /*break*/, 13]; case 13: sdkInstallSpinner.stop("".concat(alreadyInstalled ? 'Updated' : 'Installed', " ").concat(chalk_1.default.bold.cyan(packageName), " with ").concat(chalk_1.default.bold(packageManager), ".")); return [2 /*return*/]; } }); }); } exports.installPackage = installPackage; function askForSelfHosted() { return __awaiter(this, void 0, void 0, function () { var choice, validUrl, url; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, abortIfCancelled(clack.select({ message: 'Are you using Sentry SaaS or self-hosted Sentry?', options: [ { value: 'saas', label: 'Sentry SaaS (sentry.io)' }, { value: 'self-hosted', label: 'Self-hosted/on-premise/single-tenant' }, ], }))]; case 1: choice = _a.sent(); if (choice === 'saas') { Sentry.setTag('url', SAAS_URL); Sentry.setTag('self-hosted', false); return [2 /*return*/, { url: SAAS_URL, selfHosted: false }]; } _a.label = 2; case 2: if (!(validUrl === undefined)) return [3 /*break*/, 4]; return [4 /*yield*/, abortIfCancelled(clack.text({ message: 'Please enter the URL of your self-hosted Sentry instance.', placeholder: 'https://sentry.io/', }))]; case 3: url = _a.sent(); try { validUrl = new url_1.URL(url).toString(); // We assume everywhere else that the URL ends in a slash if (!validUrl.endsWith('/')) { validUrl += '/'; } } catch (_b) { clack.log.error('Please enter a valid URL. (It should look something like "http://sentry.mydomain.com/")'); } return [3 /*break*/, 2]; case 4: Sentry.setTag('url', validUrl); Sentry.setTag('self-hosted', true); return [2 /*return*/, { url: validUrl, selfHosted: true }]; } }); }); } exports.askForSelfHosted = askForSelfHosted; function addSentryCliRc(authToken) { return __awaiter(this, void 0, void 0, function () { var clircExists, clircContents, likelyAlreadyHasAuthToken, _a, _b; return __generator(this, function (_c) { switch (_c.label) { case 0: clircExists = fs.existsSync(path.join(process.cwd(), '.sentryclirc')); if (!clircExists) return [3 /*break*/, 5]; clircContents = fs.readFileSync(path.join(process.cwd(), '.sentryclirc'), 'utf8'); likelyAlreadyHasAuthToken = !!(clircContents.includes('[auth]') && clircContents.match(/token=./g)); if (!likelyAlreadyHasAuthToken) return [3 /*break*/, 1]; clack.log.warn("".concat(chalk_1.default.bold('.sentryclirc'), " already has auth token. Will not add one.")); return [3 /*break*/, 4]; case 1: _c.trys.push([1, 3, , 4]); return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), '.sentryclirc'), "".concat(clircContents, "\n[auth]\ntoken=").concat(authToken, "\n"), { encoding: 'utf8', flag: 'w' })]; case 2: _c.sent(); clack.log.success("Added auth token to ".concat(chalk_1.default.bold('.sentryclirc'), " for you to test uploading source maps locally.")); return [3 /*break*/, 4]; case 3: _a = _c.sent(); clack.log.warning("Failed to add auth token to ".concat(chalk_1.default.bold('.sentryclirc'), ". Uploading source maps during build will likely not work locally.")); return [3 /*break*/, 4]; case 4: return [3 /*break*/, 8]; case 5: _c.trys.push([5, 7, , 8]); return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), '.sentryclirc'), "[auth]\ntoken=".concat(authToken, "\n"), { encoding: 'utf8', flag: 'w' })]; case 6: _c.sent(); clack.log.success("Created ".concat(chalk_1.default.bold('.sentryclirc'), " with auth token for you to test uploading source maps locally.")); return [3 /*break*/, 8]; case 7: _b = _c.sent(); clack.log.warning("Failed to create ".concat(chalk_1.default.bold('.sentryclirc'), " with auth token. Uploading source maps during build will likely not work locally.")); return [3 /*break*/, 8]; case 8: return [4 /*yield*/, addAuthTokenFileToGitIgnore('.sentryclirc')]; case 9: _c.sent(); return [2 /*return*/]; } }); }); } exports.addSentryCliRc = addSentryCliRc; function addDotEnvSentryBuildPluginFile(authToken) { return __awaiter(this, void 0, void 0, function () { var DOT_ENV_FILE, envVarContent, dotEnvFilePath, dotEnvFileExists, dotEnvFileContent, hasAuthToken, _a, _b; return __generator(this, function (_c) { switch (_c.label) { case 0: DOT_ENV_FILE = '.env.sentry-build-plugin'; envVarContent = "# DO NOT commit this file to your repository!\n# The SENTRY_AUTH_TOKEN variable is picked up by the Sentry Build Plugin.\n# It's used for authentication when uploading source maps.\n# You can also set this env variable in your own `.env` files and remove this file.\nSENTRY_AUTH_TOKEN=\"".concat(authToken, "\"\n"); dotEnvFilePath = path.join(process.cwd(), DOT_ENV_FILE); dotEnvFileExists = fs.existsSync(dotEnvFilePath); if (!dotEnvFileExists) return [3 /*break*/, 5]; dotEnvFileContent = fs.readFileSync(dotEnvFilePath, 'utf8'); hasAuthToken = !!dotEnvFileContent.match(/^\s*SENTRY_AUTH_TOKEN\s*=/g); if (!hasAuthToken) return [3 /*break*/, 1]; clack.log.warn("".concat(chalk_1.default.bold(DOT_ENV_FILE), " already has auth token. Will not add one.")); return [3 /*break*/, 4]; case 1: _c.trys.push([1, 3, , 4]); return [4 /*yield*/, fs.promises.writeFile(dotEnvFilePath, "".concat(dotEnvFileContent, "\n").concat(envVarContent), { encoding: 'utf8', flag: 'w', })]; case 2: _c.sent(); clack.log.success("Added auth token to ".concat(chalk_1.default.bold(DOT_ENV_FILE))); return [3 /*break*/, 4]; case 3: _a = _c.sent(); clack.log.warning("Failed to add auth token to ".concat(chalk_1.default.bold(DOT_ENV_FILE), ". Uploading source maps during build will likely not work locally.")); return [3 /*break*/, 4]; case 4: return [3 /*break*/, 8]; case 5: _c.trys.push([5, 7, , 8]); return [4 /*yield*/, fs.promises.writeFile(dotEnvFilePath, envVarContent, { encoding: 'utf8', flag: 'w', })]; case 6: _c.sent(); clack.log.success("Created ".concat(chalk_1.default.bold(DOT_ENV_FILE), " with auth token for you to test source map uploading locally.")); return [3 /*break*/, 8]; case 7: _b = _c.sent(); clack.log.warning("Failed to create ".concat(chalk_1.default.bold(DOT_ENV_FILE), " with auth token. Uploading source maps during build will likely not work locally.")); return [3 /*break*/, 8]; case 8: return [4 /*yield*/, addAuthTokenFileToGitIgnore(DOT_ENV_FILE)]; case 9: _c.sent(); return [2 /*return*/]; } }); }); } exports.addDotEnvSentryBuildPluginFile = addDotEnvSentryBuildPluginFile; function addAuthTokenFileToGitIgnore(filename) { return __awaiter(this, void 0, void 0, function () { var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 2, , 3]); return [4 /*yield*/, fs.promises.appendFile(path.join(process.cwd(), '.gitignore'), "\n# Sentry Auth Token\n".concat(filename, "\n"), { encoding: 'utf8' })]; case 1: _b.sent(); clack.log.success("Added ".concat(chalk_1.default.bold(filename), " to ").concat(chalk_1.default.bold('.gitignore'), ".")); return [3 /*break*/, 3]; case 2: _a = _b.sent(); clack.log.error("Failed adding ".concat(chalk_1.default.bold(filename), " to ").concat(chalk_1.default.bold('.gitignore'), ". Please add it manually!")); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); } function ensurePackageIsInstalled(packageJson, packageId, packageName) { return __awaiter(this, void 0, void 0, function () { var continueWithoutPackage; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!!hasPackageInstalled(packageId, packageJson)) return [3 /*break*/, 3]; return [4 /*yield*/, abortIfCancelled(clack.confirm({ message: "".concat(packageName, " does not seem to be installed. Do you still want to continue?"), initialValue: false, }))]; case 1: continueWithoutPackage = _a.sent(); if (!!continueWithoutPackage) return [3 /*break*/, 3]; return [4 /*yield*/, abort(undefined, 0)]; case 2: _a.sent(); _a.label = 3; case 3: return [2 /*return*/]; } }); }); } exports.ensurePackageIsInstalled = ensurePackageIsInstalled; function getPackageDotJson() { return __awaiter(this, void 0, void 0, function () { var packageJsonFileContents, packageJson, _a; return __generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, fs.promises .readFile(path.join(process.cwd(), 'package.json'), 'utf8') .catch(function () { clack.log.error('Could not find package.json. Make sure to run the wizard in the root of your app!'); return abort(); })]; case 1: packageJsonFileContents = _b.sent(); packageJson = undefined; _b.label = 2; case 2: _b.trys.push([2, 3, , 5]); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment packageJson = JSON.parse(packageJsonFileContents); return [3 /*break*/, 5]; case 3: _a = _b.sent(); clack.log.error('Unable to parse your package.json. Make sure it has a valid format!'); return [4 /*yield*/, abort()]; case 4: _b.sent(); return [3 /*break*/, 5]; case 5: return [2 /*return*/, packageJson || {}]; } }); }); } exports.getPackageDotJson = getPackageDotJson; function hasPackageInstalled(packageName, packageJson) { var _a, _b; return (!!((_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.dependencies) === null || _a === void 0 ? void 0 : _a[packageName]) || !!((_b = packageJson === null || packageJson === void 0 ? void 0 : packageJson.devDependencies) === null || _b === void 0 ? void 0 : _b[packageName])); } exports.hasPackageInstalled = hasPackageInstalled; function getPackageManager() { return __awaiter(this, void 0, void 0, function () { var detectedPackageManager, selectedPackageManager; return __generator(this, function (_a) { switch (_a.label) { case 0: if (fs.existsSync(path.join(process.cwd(), 'yarn.lock'))) { detectedPackageManager = 'yarn'; } else if (fs.existsSync(path.join(process.cwd(), 'package-lock.json'))) { detectedPackageManager = 'npm'; } else if (fs.existsSync(path.join(process.cwd(), 'pnpm-lock.yaml'))) { detectedPackageManager = 'pnpm'; } if (detectedPackageManager) { return [2 /*return*/, detectedPackageManager]; } return [4 /*yield*/, abortIfCancelled(clack.select({ message: 'Please select your package manager.', options: [ { value: 'npm', label: 'Npm' }, { value: 'yarn', label: 'Yarn' }, { value: 'pnpm', label: 'Pnpm' }, ], }))]; case 1: selectedPackageManager = _a.sent(); Sentry.setTag('package-manager', selectedPackageManager); return [2 /*return*/, selectedPackageManager]; } }); }); } //# sourceMappingURL=clack-utils.js.map