@sentry/wizard 3.12.0 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/lib/Steps/ChooseIntegration.js +1 -0
  3. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  4. package/dist/package.json +2 -2
  5. package/dist/src/android/android-wizard.js +8 -8
  6. package/dist/src/android/android-wizard.js.map +1 -1
  7. package/dist/src/apple/apple-wizard.js +1 -1
  8. package/dist/src/apple/apple-wizard.js.map +1 -1
  9. package/dist/src/nextjs/nextjs-wizard.d.ts +1 -0
  10. package/dist/src/nextjs/nextjs-wizard.js +257 -163
  11. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  12. package/dist/src/nextjs/templates.d.ts +1 -1
  13. package/dist/src/nextjs/templates.js +2 -2
  14. package/dist/src/nextjs/templates.js.map +1 -1
  15. package/dist/src/nextjs/utils.d.ts +1 -0
  16. package/dist/src/nextjs/utils.js +25 -0
  17. package/dist/src/nextjs/utils.js.map +1 -0
  18. package/dist/src/remix/remix-wizard.js +13 -11
  19. package/dist/src/remix/remix-wizard.js.map +1 -1
  20. package/dist/src/remix/sdk-setup.d.ts +5 -1
  21. package/dist/src/remix/sdk-setup.js +13 -6
  22. package/dist/src/remix/sdk-setup.js.map +1 -1
  23. package/dist/src/sourcemaps/sourcemaps-wizard.js +1 -1
  24. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  25. package/dist/src/sourcemaps/tools/sentry-cli.d.ts +9 -0
  26. package/dist/src/sourcemaps/tools/sentry-cli.js +26 -22
  27. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  28. package/dist/src/sourcemaps/tools/tsc.d.ts +6 -0
  29. package/dist/src/sourcemaps/tools/tsc.js +98 -17
  30. package/dist/src/sourcemaps/tools/tsc.js.map +1 -1
  31. package/dist/src/sourcemaps/tools/vite.js +3 -13
  32. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  33. package/dist/src/sourcemaps/tools/webpack.js +3 -13
  34. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  35. package/dist/src/sveltekit/sdk-setup.js +122 -48
  36. package/dist/src/sveltekit/sdk-setup.js.map +1 -1
  37. package/dist/src/sveltekit/sveltekit-wizard.d.ts +1 -0
  38. package/dist/src/sveltekit/sveltekit-wizard.js +113 -42
  39. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  40. package/dist/src/sveltekit/utils.d.ts +2 -0
  41. package/dist/src/sveltekit/utils.js +48 -0
  42. package/dist/src/sveltekit/utils.js.map +1 -0
  43. package/dist/src/telemetry.d.ts +1 -0
  44. package/dist/src/telemetry.js +27 -12
  45. package/dist/src/telemetry.js.map +1 -1
  46. package/dist/src/utils/ast-utils.d.ts +70 -0
  47. package/dist/src/utils/ast-utils.js +152 -1
  48. package/dist/src/utils/ast-utils.js.map +1 -1
  49. package/dist/src/utils/clack-utils.d.ts +49 -7
  50. package/dist/src/utils/clack-utils.js +238 -168
  51. package/dist/src/utils/clack-utils.js.map +1 -1
  52. package/dist/src/utils/package-manager.d.ts +5 -0
  53. package/dist/src/utils/package-manager.js +23 -14
  54. package/dist/src/utils/package-manager.js.map +1 -1
  55. package/dist/test/sourcemaps/tools/sentry-cli.test.d.ts +1 -0
  56. package/dist/test/sourcemaps/tools/sentry-cli.test.js +112 -0
  57. package/dist/test/sourcemaps/tools/sentry-cli.test.js.map +1 -0
  58. package/dist/test/sourcemaps/tools/tsc.test.d.ts +1 -0
  59. package/dist/test/sourcemaps/tools/tsc.test.js +121 -0
  60. package/dist/test/sourcemaps/tools/tsc.test.js.map +1 -0
  61. package/dist/test/utils/ast-utils.test.js +157 -26
  62. package/dist/test/utils/ast-utils.test.js.map +1 -1
  63. package/lib/Steps/ChooseIntegration.ts +1 -0
  64. package/package.json +2 -2
  65. package/src/android/android-wizard.ts +12 -10
  66. package/src/apple/apple-wizard.ts +2 -2
  67. package/src/nextjs/nextjs-wizard.ts +277 -198
  68. package/src/nextjs/templates.ts +3 -2
  69. package/src/nextjs/utils.ts +21 -0
  70. package/src/remix/remix-wizard.ts +15 -20
  71. package/src/remix/sdk-setup.ts +20 -5
  72. package/src/sourcemaps/sourcemaps-wizard.ts +2 -2
  73. package/src/sourcemaps/tools/sentry-cli.ts +16 -9
  74. package/src/sourcemaps/tools/tsc.ts +133 -28
  75. package/src/sourcemaps/tools/vite.ts +15 -39
  76. package/src/sourcemaps/tools/webpack.ts +16 -39
  77. package/src/sveltekit/sdk-setup.ts +109 -37
  78. package/src/sveltekit/sveltekit-wizard.ts +86 -21
  79. package/src/sveltekit/utils.ts +50 -0
  80. package/src/telemetry.ts +22 -11
  81. package/src/utils/ast-utils.ts +180 -0
  82. package/src/utils/clack-utils.ts +238 -149
  83. package/src/utils/package-manager.ts +24 -12
  84. package/test/sourcemaps/tools/sentry-cli.test.ts +51 -0
  85. package/test/sourcemaps/tools/tsc.test.ts +181 -0
  86. package/test/utils/ast-utils.test.ts +233 -32
@@ -71,7 +71,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
71
71
  return (mod && mod.__esModule) ? mod : { "default": mod };
72
72
  };
73
73
  Object.defineProperty(exports, "__esModule", { value: true });
74
- exports.createNewConfigFile = exports.showCopyPasteInstructions = exports.askForToolConfigPath = exports.getOrAskForProjectData = exports.isUsingTypeScript = exports.getPackageDotJson = exports.ensurePackageIsInstalled = exports.addDotEnvSentryBuildPluginFile = exports.addSentryCliConfig = exports.installPackage = exports.askForItemSelection = exports.askToInstallSentryCLI = exports.confirmContinueEvenThoughNoGitRepo = exports.printWelcome = exports.abortIfCancelled = exports.abort = exports.sourceMapsCliSetupConfig = exports.SENTRY_PROPERTIES_FILE = exports.SENTRY_CLI_RC_FILE = exports.SENTRY_DOT_ENV_FILE = void 0;
74
+ exports.createNewConfigFile = exports.makeCodeSnippet = exports.showCopyPasteInstructions = exports.askForToolConfigPath = exports.getOrAskForProjectData = exports.isUsingTypeScript = exports.getPackageDotJson = exports.ensurePackageIsInstalled = exports.addDotEnvSentryBuildPluginFile = exports.addSentryCliConfig = exports.installPackage = exports.askForItemSelection = exports.askToInstallSentryCLI = exports.confirmContinueIfNoOrDirtyGitRepo = exports.printWelcome = exports.abortIfCancelled = exports.abort = exports.sourceMapsCliSetupConfig = exports.SENTRY_PROPERTIES_FILE = exports.SENTRY_CLI_RC_FILE = exports.SENTRY_DOT_ENV_FILE = void 0;
75
75
  // @ts-ignore - clack is ESM and TS complains about that. It works though
76
76
  var clack = __importStar(require("@clack/prompts"));
77
77
  var axios_1 = __importDefault(require("axios"));
@@ -79,6 +79,7 @@ var chalk_1 = __importDefault(require("chalk"));
79
79
  var childProcess = __importStar(require("child_process"));
80
80
  var fs = __importStar(require("fs"));
81
81
  var path = __importStar(require("path"));
82
+ var os = __importStar(require("os"));
82
83
  var timers_1 = require("timers");
83
84
  var url_1 = require("url");
84
85
  var Sentry = __importStar(require("@sentry/node"));
@@ -175,50 +176,90 @@ function printWelcome(options) {
175
176
  console.log('');
176
177
  clack.intro(chalk_1.default.inverse(" ".concat(options.wizardName, " ")));
177
178
  var welcomeText = options.message ||
178
- 'This Wizard will help you set up Sentry for your application.\nThank you for using Sentry :)';
179
+ "The ".concat(options.wizardName, " will help you set up Sentry for your application.\nThank you for using Sentry :)");
179
180
  if (options.promoCode) {
180
- welcomeText += "\n\nUsing promo-code: ".concat(options.promoCode);
181
+ welcomeText = "".concat(welcomeText, "\n\nUsing promo-code: ").concat(options.promoCode);
181
182
  }
182
183
  if (wizardPackage.version) {
183
- welcomeText += "\n\nVersion: ".concat(wizardPackage.version);
184
+ welcomeText = "".concat(welcomeText, "\n\nVersion: ").concat(wizardPackage.version);
184
185
  }
185
186
  if (options.telemetryEnabled) {
186
- welcomeText += "\n\nYou are using the Sentry Wizard with telemetry enabled. This helps us improve the Wizard.\nYou can disable it at any time by running `sentry-wizard --disable-telemetry`.";
187
+ welcomeText = "".concat(welcomeText, "\n\nThis wizard sends telemetry data and crash reports to Sentry. This helps us improve the Wizard.\nYou can turn this off at any time by running ").concat(chalk_1.default.cyanBright('sentry-wizard --disable-telemetry'), ".");
187
188
  }
188
189
  clack.note(welcomeText);
189
190
  }
190
191
  exports.printWelcome = printWelcome;
191
- function confirmContinueEvenThoughNoGitRepo() {
192
+ function confirmContinueIfNoOrDirtyGitRepo() {
192
193
  return __awaiter(this, void 0, void 0, function () {
193
- var _a, continueWithoutGit;
194
- return __generator(this, function (_b) {
195
- switch (_b.label) {
196
- case 0:
197
- _b.trys.push([0, 1, , 5]);
198
- childProcess.execSync('git rev-parse --is-inside-work-tree', {
199
- stdio: 'ignore',
194
+ var _this = this;
195
+ return __generator(this, function (_a) {
196
+ return [2 /*return*/, (0, telemetry_1.traceStep)('check-git-status', function () { return __awaiter(_this, void 0, void 0, function () {
197
+ var continueWithoutGit, uncommittedOrUntrackedFiles, continueWithDirtyRepo;
198
+ return __generator(this, function (_a) {
199
+ switch (_a.label) {
200
+ case 0:
201
+ if (!!isInGitRepo()) return [3 /*break*/, 3];
202
+ return [4 /*yield*/, abortIfCancelled(clack.confirm({
203
+ message: 'You are not inside a git repository. The wizard will create and update files. Do you want to continue anyway?',
204
+ }))];
205
+ case 1:
206
+ continueWithoutGit = _a.sent();
207
+ Sentry.setTag('continue-without-git', continueWithoutGit);
208
+ if (!!continueWithoutGit) return [3 /*break*/, 3];
209
+ return [4 /*yield*/, abort(undefined, 0)];
210
+ case 2:
211
+ _a.sent();
212
+ _a.label = 3;
213
+ case 3:
214
+ uncommittedOrUntrackedFiles = getUncommittedOrUntrackedFiles();
215
+ if (!uncommittedOrUntrackedFiles.length) return [3 /*break*/, 6];
216
+ clack.log.warn("You have uncommitted or untracked files in your repo:\n\n".concat(uncommittedOrUntrackedFiles.join('\n'), "\n\nThe wizard will create and update files."));
217
+ return [4 /*yield*/, abortIfCancelled(clack.confirm({
218
+ message: 'Do you want to continue anyway?',
219
+ }))];
220
+ case 4:
221
+ continueWithDirtyRepo = _a.sent();
222
+ Sentry.setTag('continue-with-dirty-repo', continueWithDirtyRepo);
223
+ if (!!continueWithDirtyRepo) return [3 /*break*/, 6];
224
+ return [4 /*yield*/, abort(undefined, 0)];
225
+ case 5:
226
+ _a.sent();
227
+ _a.label = 6;
228
+ case 6: return [2 /*return*/];
229
+ }
200
230
  });
201
- return [3 /*break*/, 5];
202
- case 1:
203
- _a = _b.sent();
204
- return [4 /*yield*/, abortIfCancelled(clack.confirm({
205
- message: 'You are not inside a git repository. The wizard will create and update files. Do you still want to continue?',
206
- }))];
207
- case 2:
208
- continueWithoutGit = _b.sent();
209
- Sentry.setTag('continue-without-git', continueWithoutGit);
210
- if (!!continueWithoutGit) return [3 /*break*/, 4];
211
- return [4 /*yield*/, abort(undefined, 0)];
212
- case 3:
213
- _b.sent();
214
- _b.label = 4;
215
- case 4: return [3 /*break*/, 5];
216
- case 5: return [2 /*return*/];
217
- }
231
+ }); })];
218
232
  });
219
233
  });
220
234
  }
221
- exports.confirmContinueEvenThoughNoGitRepo = confirmContinueEvenThoughNoGitRepo;
235
+ exports.confirmContinueIfNoOrDirtyGitRepo = confirmContinueIfNoOrDirtyGitRepo;
236
+ function isInGitRepo() {
237
+ try {
238
+ childProcess.execSync('git rev-parse --is-inside-work-tree', {
239
+ stdio: 'ignore',
240
+ });
241
+ return true;
242
+ }
243
+ catch (_a) {
244
+ return false;
245
+ }
246
+ }
247
+ function getUncommittedOrUntrackedFiles() {
248
+ try {
249
+ var gitStatus = childProcess
250
+ .execSync('git status --porcelain=v1')
251
+ .toString();
252
+ var files = gitStatus
253
+ .split(os.EOL)
254
+ .map(function (line) { return line.trim(); })
255
+ .filter(Boolean)
256
+ .map(function (f) { return "- ".concat(f.split(/\s+/)[1]); });
257
+ return files;
258
+ }
259
+ catch (_a) {
260
+ return [];
261
+ }
262
+ }
222
263
  function askToInstallSentryCLI() {
223
264
  return __awaiter(this, void 0, void 0, function () {
224
265
  return __generator(this, function (_a) {
@@ -258,121 +299,100 @@ exports.askForItemSelection = askForItemSelection;
258
299
  function installPackage(_a) {
259
300
  var packageName = _a.packageName, alreadyInstalled = _a.alreadyInstalled, _b = _a.askBeforeUpdating, askBeforeUpdating = _b === void 0 ? true : _b;
260
301
  return __awaiter(this, void 0, void 0, function () {
261
- var shouldUpdatePackage, sdkInstallSpinner, packageManager, e_1;
302
+ var _this = this;
262
303
  return __generator(this, function (_c) {
263
- switch (_c.label) {
264
- case 0:
265
- if (!(alreadyInstalled && askBeforeUpdating)) return [3 /*break*/, 2];
266
- return [4 /*yield*/, abortIfCancelled(clack.confirm({
267
- message: "The ".concat(chalk_1.default.bold.cyan(packageName), " package is already installed. Do you want to update it to the latest version?"),
268
- }))];
269
- case 1:
270
- shouldUpdatePackage = _c.sent();
271
- if (!shouldUpdatePackage) {
272
- return [2 /*return*/];
273
- }
274
- _c.label = 2;
275
- case 2:
276
- sdkInstallSpinner = clack.spinner();
277
- return [4 /*yield*/, getPackageManager()];
278
- case 3:
279
- packageManager = _c.sent();
280
- sdkInstallSpinner.start("".concat(alreadyInstalled ? 'Updating' : 'Installing', " ").concat(chalk_1.default.bold.cyan(packageName), " with ").concat(chalk_1.default.bold(packageManager.label), "."));
281
- _c.label = 4;
282
- case 4:
283
- _c.trys.push([4, 6, , 8]);
284
- return [4 /*yield*/, (0, package_manager_1.installPackageWithPackageManager)(packageManager, packageName)];
285
- case 5:
286
- _c.sent();
287
- return [3 /*break*/, 8];
288
- case 6:
289
- e_1 = _c.sent();
290
- sdkInstallSpinner.stop('Installation failed.');
291
- 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')));
292
- return [4 /*yield*/, abort()];
293
- case 7:
294
- _c.sent();
295
- return [3 /*break*/, 8];
296
- case 8:
297
- sdkInstallSpinner.stop("".concat(alreadyInstalled ? 'Updated' : 'Installed', " ").concat(chalk_1.default.bold.cyan(packageName), " with ").concat(chalk_1.default.bold(packageManager.label), "."));
298
- return [2 /*return*/];
299
- }
304
+ return [2 /*return*/, (0, telemetry_1.traceStep)('install-package', function () { return __awaiter(_this, void 0, void 0, function () {
305
+ var shouldUpdatePackage, sdkInstallSpinner, packageManager, e_1;
306
+ return __generator(this, function (_a) {
307
+ switch (_a.label) {
308
+ case 0:
309
+ if (!(alreadyInstalled && askBeforeUpdating)) return [3 /*break*/, 2];
310
+ return [4 /*yield*/, abortIfCancelled(clack.confirm({
311
+ message: "The ".concat(chalk_1.default.bold.cyan(packageName), " package is already installed. Do you want to update it to the latest version?"),
312
+ }))];
313
+ case 1:
314
+ shouldUpdatePackage = _a.sent();
315
+ if (!shouldUpdatePackage) {
316
+ return [2 /*return*/];
317
+ }
318
+ _a.label = 2;
319
+ case 2:
320
+ sdkInstallSpinner = clack.spinner();
321
+ return [4 /*yield*/, getPackageManager()];
322
+ case 3:
323
+ packageManager = _a.sent();
324
+ sdkInstallSpinner.start("".concat(alreadyInstalled ? 'Updating' : 'Installing', " ").concat(chalk_1.default.bold.cyan(packageName), " with ").concat(chalk_1.default.bold(packageManager.label), "."));
325
+ _a.label = 4;
326
+ case 4:
327
+ _a.trys.push([4, 6, , 8]);
328
+ return [4 /*yield*/, (0, package_manager_1.installPackageWithPackageManager)(packageManager, packageName)];
329
+ case 5:
330
+ _a.sent();
331
+ return [3 /*break*/, 8];
332
+ case 6:
333
+ e_1 = _a.sent();
334
+ sdkInstallSpinner.stop('Installation failed.');
335
+ 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')));
336
+ return [4 /*yield*/, abort()];
337
+ case 7:
338
+ _a.sent();
339
+ return [3 /*break*/, 8];
340
+ case 8:
341
+ sdkInstallSpinner.stop("".concat(alreadyInstalled ? 'Updated' : 'Installed', " ").concat(chalk_1.default.bold.cyan(packageName), " with ").concat(chalk_1.default.bold(packageManager.label), "."));
342
+ return [2 /*return*/];
343
+ }
344
+ });
345
+ }); })];
300
346
  });
301
347
  });
302
348
  }
303
349
  exports.installPackage = installPackage;
304
- function addOrgAndProjectToSentryCliRc(org, project, setupConfig) {
305
- return __awaiter(this, void 0, void 0, function () {
306
- var configContents, e_2;
307
- return __generator(this, function (_a) {
308
- switch (_a.label) {
309
- case 0:
310
- configContents = fs.readFileSync(path.join(process.cwd(), setupConfig.filename), 'utf8');
311
- if (!setupConfig.likelyAlreadyHasOrgAndProject(configContents)) return [3 /*break*/, 1];
312
- clack.log.warn("".concat(chalk_1.default.bold(setupConfig.filename), " already has org and project. Will not add them."));
313
- return [3 /*break*/, 4];
314
- case 1:
315
- _a.trys.push([1, 3, , 4]);
316
- return [4 /*yield*/, fs.promises.appendFile(path.join(process.cwd(), setupConfig.filename), "\n".concat(setupConfig.orgAndProjContent(org, project), "\n"))];
317
- case 2:
318
- _a.sent();
319
- return [3 /*break*/, 4];
320
- case 3:
321
- e_2 = _a.sent();
322
- clack.log.warn("".concat(chalk_1.default.bold(setupConfig.filename), " could not be updated with org and project."));
323
- return [3 /*break*/, 4];
324
- case 4: return [2 /*return*/];
325
- }
326
- });
327
- });
328
- }
329
- function addSentryCliConfig(authToken, setupConfig, orgSlug, projectSlug) {
350
+ function addSentryCliConfig(authToken, setupConfig) {
330
351
  if (setupConfig === void 0) { setupConfig = exports.sourceMapsCliSetupConfig; }
331
352
  return __awaiter(this, void 0, void 0, function () {
332
- var configExists, configContents, _a, _b;
333
- return __generator(this, function (_c) {
334
- switch (_c.label) {
335
- case 0:
336
- configExists = fs.existsSync(path.join(process.cwd(), setupConfig.filename));
337
- if (!configExists) return [3 /*break*/, 5];
338
- configContents = fs.readFileSync(path.join(process.cwd(), setupConfig.filename), 'utf8');
339
- if (!setupConfig.likelyAlreadyHasAuthToken(configContents)) return [3 /*break*/, 1];
340
- clack.log.warn("".concat(chalk_1.default.bold(setupConfig.filename), " already has auth token. Will not add one."));
341
- return [3 /*break*/, 4];
342
- case 1:
343
- _c.trys.push([1, 3, , 4]);
344
- return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), setupConfig.filename), "".concat(configContents, "\n").concat(setupConfig.tokenContent(authToken), "\n"), { encoding: 'utf8', flag: 'w' })];
345
- case 2:
346
- _c.sent();
347
- clack.log.success(chalk_1.default.greenBright("Added auth token to ".concat(chalk_1.default.bold(setupConfig.filename), " for you to test uploading ").concat(setupConfig.name, " locally.")));
348
- return [3 /*break*/, 4];
349
- case 3:
350
- _a = _c.sent();
351
- clack.log.warning("Failed to add auth token to ".concat(chalk_1.default.bold(setupConfig.filename), ". Uploading ").concat(setupConfig.name, " during build will likely not work locally."));
352
- return [3 /*break*/, 4];
353
- case 4: return [3 /*break*/, 8];
354
- case 5:
355
- _c.trys.push([5, 7, , 8]);
356
- return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), setupConfig.filename), "".concat(setupConfig.tokenContent(authToken), "\n"), { encoding: 'utf8', flag: 'w' })];
357
- case 6:
358
- _c.sent();
359
- clack.log.success(chalk_1.default.greenBright("Created ".concat(chalk_1.default.bold(setupConfig.filename), " with auth token for you to test uploading ").concat(setupConfig.name, " locally.")));
360
- return [3 /*break*/, 8];
361
- case 7:
362
- _b = _c.sent();
363
- clack.log.warning("Failed to create ".concat(chalk_1.default.bold(setupConfig.filename), " with auth token. Uploading ").concat(setupConfig.name, " during build will likely not work locally."));
364
- return [3 /*break*/, 8];
365
- case 8:
366
- if (!(orgSlug && projectSlug)) return [3 /*break*/, 10];
367
- return [4 /*yield*/, addOrgAndProjectToSentryCliRc(orgSlug, projectSlug, setupConfig)];
368
- case 9:
369
- _c.sent();
370
- _c.label = 10;
371
- case 10: return [4 /*yield*/, addAuthTokenFileToGitIgnore(setupConfig.filename)];
372
- case 11:
373
- _c.sent();
374
- return [2 /*return*/];
375
- }
353
+ var _this = this;
354
+ return __generator(this, function (_a) {
355
+ return [2 /*return*/, (0, telemetry_1.traceStep)('add-sentry-cli-config', function () { return __awaiter(_this, void 0, void 0, function () {
356
+ var configExists, configContents, _a, _b;
357
+ return __generator(this, function (_c) {
358
+ switch (_c.label) {
359
+ case 0:
360
+ configExists = fs.existsSync(path.join(process.cwd(), setupConfig.filename));
361
+ if (!configExists) return [3 /*break*/, 5];
362
+ configContents = fs.readFileSync(path.join(process.cwd(), setupConfig.filename), 'utf8');
363
+ if (!setupConfig.likelyAlreadyHasAuthToken(configContents)) return [3 /*break*/, 1];
364
+ clack.log.warn("".concat(chalk_1.default.bold(setupConfig.filename), " already has auth token. Will not add one."));
365
+ return [3 /*break*/, 4];
366
+ case 1:
367
+ _c.trys.push([1, 3, , 4]);
368
+ return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), setupConfig.filename), "".concat(configContents, "\n").concat(setupConfig.tokenContent(authToken), "\n"), { encoding: 'utf8', flag: 'w' })];
369
+ case 2:
370
+ _c.sent();
371
+ clack.log.success(chalk_1.default.greenBright("Added auth token to ".concat(chalk_1.default.bold(setupConfig.filename), " for you to test uploading ").concat(setupConfig.name, " locally.")));
372
+ return [3 /*break*/, 4];
373
+ case 3:
374
+ _a = _c.sent();
375
+ clack.log.warning("Failed to add auth token to ".concat(chalk_1.default.bold(setupConfig.filename), ". Uploading ").concat(setupConfig.name, " during build will likely not work locally."));
376
+ return [3 /*break*/, 4];
377
+ case 4: return [3 /*break*/, 8];
378
+ case 5:
379
+ _c.trys.push([5, 7, , 8]);
380
+ return [4 /*yield*/, fs.promises.writeFile(path.join(process.cwd(), setupConfig.filename), "".concat(setupConfig.tokenContent(authToken), "\n"), { encoding: 'utf8', flag: 'w' })];
381
+ case 6:
382
+ _c.sent();
383
+ clack.log.success(chalk_1.default.greenBright("Created ".concat(chalk_1.default.bold(setupConfig.filename), " with auth token for you to test uploading ").concat(setupConfig.name, " locally.")));
384
+ return [3 /*break*/, 8];
385
+ case 7:
386
+ _b = _c.sent();
387
+ clack.log.warning("Failed to create ".concat(chalk_1.default.bold(setupConfig.filename), " with auth token. Uploading ").concat(setupConfig.name, " during build will likely not work locally."));
388
+ return [3 /*break*/, 8];
389
+ case 8: return [4 /*yield*/, addAuthTokenFileToGitIgnore(setupConfig.filename)];
390
+ case 9:
391
+ _c.sent();
392
+ return [2 /*return*/];
393
+ }
394
+ });
395
+ }); })];
376
396
  });
377
397
  });
378
398
  }
@@ -451,26 +471,44 @@ function addAuthTokenFileToGitIgnore(filename) {
451
471
  });
452
472
  });
453
473
  }
474
+ /**
475
+ * Checks if @param packageId is listed as a dependency in @param packageJson.
476
+ * If not, it will ask users if they want to continue without the package.
477
+ *
478
+ * Use this function to check if e.g. a the framework of the SDK is installed
479
+ *
480
+ * @param packageJson the package.json object
481
+ * @param packageId the npm name of the package
482
+ * @param packageName a human readable name of the package
483
+ */
454
484
  function ensurePackageIsInstalled(packageJson, packageId, packageName) {
455
485
  return __awaiter(this, void 0, void 0, function () {
456
- var continueWithoutPackage;
486
+ var _this = this;
457
487
  return __generator(this, function (_a) {
458
- switch (_a.label) {
459
- case 0:
460
- if (!!(0, package_json_1.hasPackageInstalled)(packageId, packageJson)) return [3 /*break*/, 3];
461
- return [4 /*yield*/, abortIfCancelled(clack.confirm({
462
- message: "".concat(packageName, " does not seem to be installed. Do you still want to continue?"),
463
- initialValue: false,
464
- }))];
465
- case 1:
466
- continueWithoutPackage = _a.sent();
467
- if (!!continueWithoutPackage) return [3 /*break*/, 3];
468
- return [4 /*yield*/, abort(undefined, 0)];
469
- case 2:
470
- _a.sent();
471
- _a.label = 3;
472
- case 3: return [2 /*return*/];
473
- }
488
+ return [2 /*return*/, (0, telemetry_1.traceStep)('ensure-package-installed', function () { return __awaiter(_this, void 0, void 0, function () {
489
+ var installed, continueWithoutPackage;
490
+ return __generator(this, function (_a) {
491
+ switch (_a.label) {
492
+ case 0:
493
+ installed = (0, package_json_1.hasPackageInstalled)(packageId, packageJson);
494
+ Sentry.setTag("".concat(packageName.toLowerCase(), "-installed"), installed);
495
+ if (!!installed) return [3 /*break*/, 3];
496
+ Sentry.setTag("".concat(packageName.toLowerCase(), "-installed"), false);
497
+ return [4 /*yield*/, abortIfCancelled(clack.confirm({
498
+ message: "".concat(packageName, " does not seem to be installed. Do you still want to continue?"),
499
+ initialValue: false,
500
+ }))];
501
+ case 1:
502
+ continueWithoutPackage = _a.sent();
503
+ if (!!continueWithoutPackage) return [3 /*break*/, 3];
504
+ return [4 /*yield*/, abort(undefined, 0)];
505
+ case 2:
506
+ _a.sent();
507
+ _a.label = 3;
508
+ case 3: return [2 /*return*/];
509
+ }
510
+ });
511
+ }); })];
474
512
  });
475
513
  });
476
514
  }
@@ -497,7 +535,7 @@ function getPackageDotJson() {
497
535
  return [3 /*break*/, 5];
498
536
  case 3:
499
537
  _a = _b.sent();
500
- clack.log.error('Unable to parse your package.json. Make sure it has a valid format!');
538
+ clack.log.error("Unable to parse your ".concat(chalk_1.default.cyan('package.json'), ". Make sure it has a valid format!"));
501
539
  return [4 /*yield*/, abort()];
502
540
  case 4:
503
541
  _b.sent();
@@ -815,7 +853,7 @@ function askForToolConfigPath(toolName, configFileName) {
815
853
  return __generator(this, function (_a) {
816
854
  switch (_a.label) {
817
855
  case 0: return [4 /*yield*/, abortIfCancelled(clack.confirm({
818
- message: "Do you have a ".concat(toolName, " config file (e.g. ").concat(chalk_1.default.cyan(configFileName), "?"),
856
+ message: "Do you have a ".concat(toolName, " config file (e.g. ").concat(chalk_1.default.cyan(configFileName), ")?"),
819
857
  initialValue: true,
820
858
  }))];
821
859
  case 1:
@@ -856,23 +894,30 @@ exports.askForToolConfigPath = askForToolConfigPath;
856
894
  *
857
895
  * @param filename the name of the file to which the code snippet should be applied.
858
896
  * If a path is provided, only the filename will be used.
859
- * @param codeSnippet the snippet to be printed.
860
- * Make sure to follow the diff-like format of highlighting lines that require changes
861
- * and showing unchanged lines in gray.
862
897
  *
863
- * TODO: Link to wizard spec (develop) once it is live
898
+ * @param codeSnippet the snippet to be printed. Use {@link makeCodeSnippet} to create the
899
+ * diff-like format for visually highlighting unchanged or modified lines of code.
900
+ *
901
+ * @param hint (optional) a hint to be printed after the main instruction to add
902
+ * the code from @param codeSnippet to their @param filename.
903
+ *
904
+ * More guidelines on copy/paste instructions:
905
+ * @see {@link https://develop.sentry.dev/sdk/setup-wizards/#copy--paste-snippets}
906
+ *
864
907
  * TODO: refactor copy paste instructions across different wizards to use this function.
865
908
  * this might require adding a custom message parameter to the function
866
909
  */
867
- function showCopyPasteInstructions(filename, codeSnippet) {
910
+ function showCopyPasteInstructions(filename, codeSnippet, hint) {
868
911
  return __awaiter(this, void 0, void 0, function () {
869
912
  return __generator(this, function (_a) {
870
913
  switch (_a.label) {
871
914
  case 0:
872
- clack.log.step("Add the following code to your ".concat(chalk_1.default.cyan(path.basename(filename)), " file:"));
915
+ clack.log.step("Add the following code to your ".concat(chalk_1.default.cyan(path.basename(filename)), " file:").concat(hint ? chalk_1.default.dim(" (".concat(chalk_1.default.dim(hint), ")")) : ''));
916
+ // Padding the code snippet to be printed with a \n at the beginning and end
917
+ // This makes it easier to distinguish the snippet from the rest of the output
873
918
  // Intentionally logging directly to console here so that the code can be copied/pasted directly
874
919
  // eslint-disable-next-line no-console
875
- console.log("\n".concat(codeSnippet));
920
+ console.log("\n".concat(codeSnippet, "\n"));
876
921
  return [4 /*yield*/, abortIfCancelled(clack.select({
877
922
  message: 'Did you apply the snippet above?',
878
923
  options: [{ label: 'Yes, continue!', value: true }],
@@ -886,6 +931,31 @@ function showCopyPasteInstructions(filename, codeSnippet) {
886
931
  });
887
932
  }
888
933
  exports.showCopyPasteInstructions = showCopyPasteInstructions;
934
+ /**
935
+ * Crafts a code snippet that can be used to e.g.
936
+ * - print copy/paste instructions to the console
937
+ * - create a new config file.
938
+ *
939
+ * @param colors set this to true if you want the final snippet to be colored.
940
+ * This is useful for printing the snippet to the console as part of copy/paste instructions.
941
+ *
942
+ * @param callback the callback that returns the formatted code snippet.
943
+ * It exposes takes the helper functions for marking code as unchaned, new or removed.
944
+ * These functions no-op if no special formatting should be applied
945
+ * and otherwise apply the appropriate formatting/coloring.
946
+ * (@see {@link CodeSnippetFormatter})
947
+ *
948
+ * @see {@link showCopyPasteInstructions} for the helper with which to display the snippet in the console.
949
+ *
950
+ * @returns a string containing the final, formatted code snippet.
951
+ */
952
+ function makeCodeSnippet(colors, callback) {
953
+ var unchanged = function (txt) { return (colors ? chalk_1.default.grey(txt) : txt); };
954
+ var plus = function (txt) { return (colors ? chalk_1.default.greenBright(txt) : txt); };
955
+ var minus = function (txt) { return (colors ? chalk_1.default.redBright(txt) : txt); };
956
+ return callback(unchanged, plus, minus);
957
+ }
958
+ exports.makeCodeSnippet = makeCodeSnippet;
889
959
  /**
890
960
  * Creates a new config file with the given @param filepath and @param codeSnippet.
891
961
  *
@@ -905,7 +975,7 @@ exports.showCopyPasteInstructions = showCopyPasteInstructions;
905
975
  */
906
976
  function createNewConfigFile(filepath, codeSnippet, moreInformation) {
907
977
  return __awaiter(this, void 0, void 0, function () {
908
- var prettyFilename, e_3;
978
+ var prettyFilename, e_2;
909
979
  return __generator(this, function (_a) {
910
980
  switch (_a.label) {
911
981
  case 0:
@@ -926,8 +996,8 @@ function createNewConfigFile(filepath, codeSnippet, moreInformation) {
926
996
  }
927
997
  return [2 /*return*/, true];
928
998
  case 3:
929
- e_3 = _a.sent();
930
- (0, debug_1.debug)(e_3);
999
+ e_2 = _a.sent();
1000
+ (0, debug_1.debug)(e_2);
931
1001
  clack.log.warn("Could not create a new ".concat(prettyFilename, " file. Please create one manually and follow the instructions below."));
932
1002
  return [3 /*break*/, 4];
933
1003
  case 4: return [2 /*return*/, false];