@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
@@ -4,7 +4,7 @@ import chalk from 'chalk';
4
4
 
5
5
  import {
6
6
  addSentryCliConfig,
7
- confirmContinueEvenThoughNoGitRepo,
7
+ confirmContinueIfNoOrDirtyGitRepo,
8
8
  ensurePackageIsInstalled,
9
9
  getOrAskForProjectData,
10
10
  getPackageDotJson,
@@ -45,7 +45,7 @@ async function runRemixWizardWithTelemetry(
45
45
  telemetryEnabled: options.telemetryEnabled,
46
46
  });
47
47
 
48
- await confirmContinueEvenThoughNoGitRepo();
48
+ await confirmContinueIfNoOrDirtyGitRepo();
49
49
 
50
50
  const remixConfig = await loadRemixConfig();
51
51
  const packageJson = await getPackageDotJson();
@@ -53,33 +53,28 @@ async function runRemixWizardWithTelemetry(
53
53
  // We expect `@remix-run/dev` to be installed for every Remix project
54
54
  await ensurePackageIsInstalled(packageJson, '@remix-run/dev', 'Remix');
55
55
 
56
- const { selectedProject, authToken } = await getOrAskForProjectData(
57
- options,
58
- 'javascript-remix',
59
- );
56
+ const { selectedProject, authToken, sentryUrl } =
57
+ await getOrAskForProjectData(options, 'javascript-remix');
60
58
 
61
- await traceStep('Install Sentry SDK', () =>
62
- installPackage({
63
- packageName: '@sentry/remix',
64
- alreadyInstalled: hasPackageInstalled('@sentry/remix', packageJson),
65
- }),
66
- );
59
+ await installPackage({
60
+ packageName: '@sentry/remix',
61
+ alreadyInstalled: hasPackageInstalled('@sentry/remix', packageJson),
62
+ });
67
63
 
68
64
  const dsn = selectedProject.keys[0].dsn.public;
69
65
 
70
66
  const isTS = isUsingTypeScript();
71
67
  const isV2 = isRemixV2(remixConfig, packageJson);
72
68
 
73
- await addSentryCliConfig(
74
- authToken,
75
- sourceMapsCliSetupConfig,
76
- selectedProject.organization.slug,
77
- selectedProject.name,
78
- );
69
+ await addSentryCliConfig(authToken, sourceMapsCliSetupConfig);
79
70
 
80
71
  await traceStep('Update build script for sourcemap uploads', async () => {
81
72
  try {
82
- await updateBuildScript();
73
+ await updateBuildScript({
74
+ org: selectedProject.organization.slug,
75
+ project: selectedProject.name,
76
+ url: sentryUrl,
77
+ });
83
78
  } catch (e) {
84
79
  clack.log
85
80
  .warn(`Could not update build script to generate and upload sourcemaps.
@@ -110,7 +105,7 @@ async function runRemixWizardWithTelemetry(
110
105
 
111
106
  await traceStep('Initialize Sentry on server entry', async () => {
112
107
  try {
113
- await initializeSentryOnEntryServer(dsn, isTS, isV2);
108
+ await initializeSentryOnEntryServer(dsn, isV2, isTS);
114
109
  } catch (e) {
115
110
  clack.log.warn(`Could not initialize Sentry on server entry.
116
111
  Please do it manually using instructions from https://docs.sentry.io/platforms/javascript/guides/remix/`);
@@ -12,7 +12,7 @@ import * as url from 'url';
12
12
  // @ts-expect-error - clack is ESM and TS complains about that. It works though
13
13
  import clack from '@clack/prompts';
14
14
  import chalk from 'chalk';
15
- import { parse } from 'semver';
15
+ import { gte, minVersion } from 'semver';
16
16
 
17
17
  // @ts-expect-error - magicast is ESM and TS complains about that. It works though
18
18
  import { builders, generateCode, loadFile, writeFile } from 'magicast';
@@ -97,8 +97,17 @@ export function isRemixV2(
97
97
  packageJson: PackageDotJson,
98
98
  ): boolean {
99
99
  const remixVersion = getPackageVersion('@remix-run/react', packageJson);
100
- const remixVersionMajor = remixVersion && parse(remixVersion)?.major;
101
- const isV2Remix = remixVersionMajor && remixVersionMajor >= 2;
100
+ if (!remixVersion) {
101
+ return false;
102
+ }
103
+
104
+ const minVer = minVersion(remixVersion);
105
+
106
+ if (!minVer) {
107
+ return false;
108
+ }
109
+
110
+ const isV2Remix = gte(minVer, '2.0.0');
102
111
 
103
112
  return isV2Remix || remixConfig?.future?.v2_errorBoundary || false;
104
113
  }
@@ -151,7 +160,11 @@ export async function instrumentRootRoute(
151
160
  /* eslint-enable @typescript-eslint/no-unsafe-member-access */
152
161
  }
153
162
 
154
- export async function updateBuildScript(): Promise<void> {
163
+ export async function updateBuildScript(args: {
164
+ org: string;
165
+ project: string;
166
+ url?: string;
167
+ }): Promise<void> {
155
168
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
156
169
  // Add sourcemaps option to build script
157
170
  const packageJsonPath = path.join(process.cwd(), 'package.json');
@@ -166,7 +179,9 @@ export async function updateBuildScript(): Promise<void> {
166
179
 
167
180
  if (!packageJson.scripts.build) {
168
181
  packageJson.scripts.build =
169
- 'remix build --sourcemap && sentry-upload-sourcemaps';
182
+ `remix build --sourcemap && sentry-upload-sourcemaps --org ${args.org} --project ${args.project}` +
183
+ (args.url ? ` --url ${args.url}` : '');
184
+
170
185
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
171
186
  } else if (packageJson.scripts.build.includes('remix build')) {
172
187
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
@@ -6,7 +6,7 @@ import * as Sentry from '@sentry/node';
6
6
  import {
7
7
  abort,
8
8
  abortIfCancelled,
9
- confirmContinueEvenThoughNoGitRepo,
9
+ confirmContinueIfNoOrDirtyGitRepo,
10
10
  SENTRY_DOT_ENV_FILE,
11
11
  printWelcome,
12
12
  SENTRY_CLI_RC_FILE,
@@ -70,7 +70,7 @@ You can turn this off by running the wizard with the '--disable-telemetry' flag.
70
70
  return;
71
71
  }
72
72
 
73
- await traceStep('detect-git', confirmContinueEvenThoughNoGitRepo);
73
+ await confirmContinueIfNoOrDirtyGitRepo();
74
74
 
75
75
  await traceStep('check-sdk-version', ensureMinimumSdkVersionIsInstalled);
76
76
 
@@ -1,5 +1,5 @@
1
1
  // @ts-ignore - clack is ESM and TS complains about that. It works though
2
- import clack from '@clack/prompts';
2
+ import * as clack from '@clack/prompts';
3
3
  import chalk from 'chalk';
4
4
  import * as Sentry from '@sentry/node';
5
5
  import * as path from 'path';
@@ -14,7 +14,7 @@ import {
14
14
  import { SourceMapUploadToolConfigurationOptions } from './types';
15
15
  import { hasPackageInstalled, PackageDotJson } from '../../utils/package-json';
16
16
  import { traceStep } from '../../telemetry';
17
- import { detectPackageManger } from '../../utils/package-manager';
17
+ import { detectPackageManger, NPM } from '../../utils/package-manager';
18
18
 
19
19
  const SENTRY_NPM_SCRIPT_NAME = 'sentry:sourcemaps';
20
20
 
@@ -194,7 +194,7 @@ async function askShouldAddToBuildCommand(): Promise<boolean> {
194
194
  *
195
195
  * @param packageDotJson The package.json which will be modified.
196
196
  */
197
- async function addSentryCommandToBuildCommand(
197
+ export async function addSentryCommandToBuildCommand(
198
198
  packageDotJson: PackageDotJson,
199
199
  ): Promise<void> {
200
200
  // This usually shouldn't happen because earlier we added the
@@ -205,8 +205,7 @@ async function addSentryCommandToBuildCommand(
205
205
  (s) => s !== SENTRY_NPM_SCRIPT_NAME,
206
206
  );
207
207
 
208
- const packageManager = detectPackageManger();
209
- const packageManagerName = packageManager?.name ?? 'npm';
208
+ const packageManager = detectPackageManger() ?? NPM;
210
209
 
211
210
  // Heuristic to pre-select the build command:
212
211
  // Often, 'build' is the prod build command, so we favour it.
@@ -221,7 +220,7 @@ async function addSentryCommandToBuildCommand(
221
220
  (await abortIfCancelled(
222
221
  clack.confirm({
223
222
  message: `Is ${chalk.cyan(
224
- `${packageManagerName} run ${buildCommand}`,
223
+ `${packageManager.runScriptCommand} ${buildCommand}`,
225
224
  )} your production build command?`,
226
225
  }),
227
226
  ));
@@ -229,7 +228,7 @@ async function addSentryCommandToBuildCommand(
229
228
  if (allNpmScripts.length && (!buildCommand || !isProdBuildCommand)) {
230
229
  buildCommand = await abortIfCancelled(
231
230
  clack.select({
232
- message: `Which ${packageManagerName} command in your ${chalk.cyan(
231
+ message: `Which ${packageManager.name} command in your ${chalk.cyan(
233
232
  'package.json',
234
233
  )} builds your application for production?`,
235
234
  options: allNpmScripts
@@ -252,10 +251,18 @@ Please add it manually to your prod build command.`,
252
251
  return;
253
252
  }
254
253
 
254
+ const oldCommand = packageDotJson.scripts[buildCommand];
255
+ if (!oldCommand) {
256
+ // very unlikely to happen but nevertheless
257
+ clack.log.warn(
258
+ `\`${buildCommand}\` doesn't seem to be part of your package.json scripts`,
259
+ );
260
+ return;
261
+ }
262
+
255
263
  packageDotJson.scripts[
256
264
  buildCommand
257
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
258
- ] = `${packageDotJson.scripts[buildCommand]} && ${packageManager} run ${SENTRY_NPM_SCRIPT_NAME}`;
265
+ ] = `${oldCommand} && ${packageManager.runScriptCommand} ${SENTRY_NPM_SCRIPT_NAME}`;
259
266
 
260
267
  await fs.promises.writeFile(
261
268
  path.join(process.cwd(), 'package.json'),
@@ -1,39 +1,144 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ import * as recast from 'recast';
5
+
6
+ import * as Sentry from '@sentry/node';
7
+
1
8
  // @ts-ignore - clack is ESM and TS complains about that. It works though
2
- import clack, { select } from '@clack/prompts';
9
+ import * as clack from '@clack/prompts';
3
10
  import chalk from 'chalk';
4
- import { abortIfCancelled } from '../../utils/clack-utils';
5
-
6
- export async function configureTscSourcemapGenerationFlow(): Promise<void> {
7
- clack.log.step(
8
- `Add the following code to your ${chalk.bold(
9
- 'tsconfig.json',
10
- )} file: ${chalk.dim(
11
- '(This ensures that source maps are generated correctly)',
12
- )}`,
13
- );
14
11
 
15
- // Intentially logging directly to console here so that the code can be copied/pasted directly
16
- // eslint-disable-next-line no-console
17
- console.log(codeSnippet);
12
+ import {
13
+ askForToolConfigPath,
14
+ createNewConfigFile,
15
+ makeCodeSnippet,
16
+ showCopyPasteInstructions,
17
+ } from '../../utils/clack-utils';
18
+ import {
19
+ findFile,
20
+ getOrSetObjectProperty,
21
+ parseJsonC,
22
+ printJsonC,
23
+ setOrUpdateObjectProperty,
24
+ } from '../../utils/ast-utils';
25
+ import { debug } from '../../utils/debug';
18
26
 
19
- await abortIfCancelled(
20
- select({
21
- message: 'Did you update your config as shown in the snippet above?',
22
- options: [{ label: 'Yes, continue!', value: true }],
23
- initialValue: true,
24
- }),
25
- );
26
- }
27
+ const b = recast.types.builders;
27
28
 
28
- const codeSnippet = chalk.gray(`
29
- {
29
+ const getCodeSnippet = (colors: boolean) =>
30
+ makeCodeSnippet(colors, (unchanged, plus, _) =>
31
+ unchanged(
32
+ `{
30
33
  "compilerOptions": {
31
- ${chalk.greenBright('"sourceMap": true,')}
32
- ${chalk.greenBright('"inlineSources": true,')}
34
+ ${plus('"sourceMap": true,')}
35
+ ${plus('"inlineSources": true,')}
33
36
 
34
37
  // Set \`sourceRoot\` to "/" to strip the build path prefix from
35
38
  // generated source code references. This will improve issue grouping in Sentry.
36
- ${chalk.greenBright('"sourceRoot": "/"')}
39
+ ${plus('"sourceRoot": "/"')}
40
+ }
41
+ }`,
42
+ ),
43
+ );
44
+
45
+ export async function configureTscSourcemapGenerationFlow(): Promise<void> {
46
+ const tsConfigPath =
47
+ findFile(path.join(process.cwd(), 'tsconfig'), ['.json']) ??
48
+ (await askForToolConfigPath('TypeScript', 'tsconfig.json'));
49
+
50
+ let successfullyAdded = false;
51
+ if (tsConfigPath) {
52
+ successfullyAdded = await enableSourcemaps(tsConfigPath);
53
+ } else {
54
+ successfullyAdded = await createNewConfigFile(
55
+ path.join(process.cwd(), 'tsconfig.json'),
56
+ getCodeSnippet(false),
57
+ );
58
+ Sentry.setTag('created-new-config', successfullyAdded ? 'success' : 'fail');
59
+ }
60
+
61
+ if (successfullyAdded) {
62
+ Sentry.setTag('ast-mod', 'success');
63
+ clack.log.info(
64
+ `We recommend checking the ${
65
+ tsConfigPath ? 'modified' : 'added'
66
+ } file after the wizard finished to ensure it works with your build setup.`,
67
+ );
68
+ } else {
69
+ Sentry.setTag('ast-mod', 'fail');
70
+ await showCopyPasteInstructions(
71
+ 'tsconfig.json',
72
+ getCodeSnippet(true),
73
+ 'This ensures that source maps are generated correctly',
74
+ );
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Modifies tsconfig.json (@param tsConfigPath) to enable source maps generation.
80
+ *
81
+ * Exported only for testing
82
+ */
83
+ export async function enableSourcemaps(tsConfigPath: string): Promise<boolean> {
84
+ try {
85
+ const tsConfig = await fs.promises.readFile(tsConfigPath, 'utf-8');
86
+
87
+ const { ast, jsonObject } = parseJsonC(tsConfig.toString());
88
+
89
+ if (!jsonObject || !ast) {
90
+ // this will only happen if the input file isn't valid JSON-C
91
+ Sentry.setTag('ast-mod-fail-reason', 'original-file-invalid');
92
+ return false;
93
+ }
94
+
95
+ const compilerOptionsProp = getOrSetObjectProperty(
96
+ jsonObject,
97
+ 'compilerOptions',
98
+ b.objectExpression([]),
99
+ );
100
+
101
+ const compilerOptionsObj = compilerOptionsProp.value;
102
+
103
+ if (!compilerOptionsObj || compilerOptionsObj.type !== 'ObjectExpression') {
104
+ // a valid compilerOptions prop should always be an object expression
105
+ Sentry.setTag('ast-mod-fail-reason', 'original-file-invalid');
106
+ return false;
107
+ }
108
+
109
+ setOrUpdateObjectProperty(
110
+ compilerOptionsObj,
111
+ 'sourceMap',
112
+ b.booleanLiteral(true),
113
+ );
114
+
115
+ setOrUpdateObjectProperty(
116
+ compilerOptionsObj,
117
+ 'inlineSources',
118
+ b.booleanLiteral(true),
119
+ );
120
+
121
+ setOrUpdateObjectProperty(
122
+ compilerOptionsObj,
123
+ 'sourceRoot',
124
+ b.stringLiteral('/'),
125
+ 'Set `sourceRoot` to "/" to strip the build path prefix\nfrom generated source code references.\nThis improves issue grouping in Sentry.',
126
+ );
127
+
128
+ const code = printJsonC(ast);
129
+
130
+ await fs.promises.writeFile(tsConfigPath, code);
131
+
132
+ clack.log.success(
133
+ `Enabled source maps generation in ${chalk.cyan(
134
+ path.basename(tsConfigPath || 'tsconfig.json'),
135
+ )}.`,
136
+ );
137
+
138
+ return true;
139
+ } catch (e) {
140
+ debug(e);
141
+ Sentry.setTag('ast-mod-fail-reason', 'insertion-fail');
142
+ return false;
37
143
  }
38
144
  }
39
- `);
@@ -19,6 +19,7 @@ import {
19
19
  createNewConfigFile,
20
20
  getPackageDotJson,
21
21
  installPackage,
22
+ makeCodeSnippet,
22
23
  showCopyPasteInstructions,
23
24
  } from '../../utils/clack-utils';
24
25
  import { hasPackageInstalled } from '../../utils/package-json';
@@ -36,52 +37,27 @@ import { debug } from '../../utils/debug';
36
37
  const getViteConfigSnippet = (
37
38
  options: SourceMapUploadToolConfigurationOptions,
38
39
  colors: boolean,
39
- ) => {
40
- const rawImportStmt =
41
- 'import { sentryVitePlugin } from "@sentry/vite-plugin";';
42
- const rawGenerateSourceMapsOption =
43
- 'sourcemap: true, // Source map generation must be turned on';
44
- const rawSentryVitePluginFunction = `sentryVitePlugin({
45
- authToken: process.env.SENTRY_AUTH_TOKEN,
46
- org: "${options.orgSlug}",
47
- project: "${options.projectSlug}",${
48
- options.selfHosted ? `\n url: "${options.url}",` : ''
49
- }
50
- }),`;
51
-
52
- const importStmt = colors ? chalk.greenBright(rawImportStmt) : rawImportStmt;
53
- const generateSourceMapsOption = colors
54
- ? chalk.greenBright(rawGenerateSourceMapsOption)
55
- : rawGenerateSourceMapsOption;
56
- const sentryVitePluginFunction = colors
57
- ? chalk.greenBright(rawSentryVitePluginFunction)
58
- : rawSentryVitePluginFunction;
59
-
60
- const code = getViteConfigContent(
61
- importStmt,
62
- generateSourceMapsOption,
63
- sentryVitePluginFunction,
64
- );
65
- return colors ? chalk.gray(code) : code;
66
- };
67
-
68
- const getViteConfigContent = (
69
- importStmt: string,
70
- generateSourceMapsOption: string,
71
- sentryVitePluginFunction: string,
72
- ) => `import { defineConfig } from "vite";
73
- ${importStmt}
40
+ ) =>
41
+ makeCodeSnippet(colors, (unchanged, plus, _) =>
42
+ unchanged(`import { defineConfig } from "vite";
43
+ ${plus('import { sentryVitePlugin } from "@sentry/vite-plugin";')}
74
44
 
75
45
  export default defineConfig({
76
46
  build: {
77
- ${generateSourceMapsOption}
47
+ ${plus('sourcemap: true, // Source map generation must be turned on')}
78
48
  },
79
49
  plugins: [
80
50
  // Put the Sentry vite plugin after all other plugins
81
- ${sentryVitePluginFunction}
51
+ ${plus(`sentryVitePlugin({
52
+ authToken: process.env.SENTRY_AUTH_TOKEN,
53
+ org: "${options.orgSlug}",
54
+ project: "${options.projectSlug}",${
55
+ options.selfHosted ? `\n url: "${options.url}",` : ''
56
+ }
57
+ }),`)}
82
58
  ],
83
- });
84
- `;
59
+ });`),
60
+ );
85
61
 
86
62
  export const configureVitePlugin: SourceMapUploadToolConfigurationFunction =
87
63
  async (options) => {
@@ -18,6 +18,7 @@ import {
18
18
  createNewConfigFile,
19
19
  getPackageDotJson,
20
20
  installPackage,
21
+ makeCodeSnippet,
21
22
  showCopyPasteInstructions,
22
23
  } from '../../utils/clack-utils';
23
24
  import { hasPackageInstalled } from '../../utils/package-json';
@@ -33,51 +34,27 @@ import { debug } from '../../utils/debug';
33
34
  const getCodeSnippet = (
34
35
  options: SourceMapUploadToolConfigurationOptions,
35
36
  colors: boolean,
36
- ) => {
37
- const rawImportStmt =
38
- 'const { sentryWebpackPlugin } = require("@sentry/webpack-plugin");';
39
- const rawGenerateSourceMapsOption =
40
- 'devtool: "source-map", // Source map generation must be turned on';
41
- const rawSentryWebpackPluginFunction = `sentryWebpackPlugin({
42
- authToken: process.env.SENTRY_AUTH_TOKEN,
43
- org: "${options.orgSlug}",
44
- project: "${options.projectSlug}",${
45
- options.selfHosted ? `\n url: "${options.url}",` : ''
46
- }
47
- })`;
48
-
49
- const importStmt = colors ? chalk.greenBright(rawImportStmt) : rawImportStmt;
50
- const generateSourceMapsOption = colors
51
- ? chalk.greenBright(rawGenerateSourceMapsOption)
52
- : rawGenerateSourceMapsOption;
53
- const sentryWebpackPluginFunction = colors
54
- ? chalk.greenBright(rawSentryWebpackPluginFunction)
55
- : rawSentryWebpackPluginFunction;
56
-
57
- const code = getWebpackConfigContent(
58
- importStmt,
59
- generateSourceMapsOption,
60
- sentryWebpackPluginFunction,
61
- );
62
-
63
- return colors ? chalk.gray(code) : code;
64
- };
65
-
66
- const getWebpackConfigContent = (
67
- importStmt: string,
68
- generateSourceMapsOption: string,
69
- sentryWebpackPluginFunction: string,
70
- ) => `${importStmt}
37
+ ) =>
38
+ makeCodeSnippet(colors, (unchanged, plus) =>
39
+ unchanged(`${plus(
40
+ 'const { sentryWebpackPlugin } = require("@sentry/webpack-plugin");',
41
+ )}
71
42
 
72
43
  module.exports = {
73
44
  // ... other options
74
- ${generateSourceMapsOption},
45
+ ${plus('devtool: "source-map", // Source map generation must be turned on')}
75
46
  plugins: [
76
47
  // Put the Sentry Webpack plugin after all other plugins
77
- ${sentryWebpackPluginFunction},
48
+ ${plus(`sentryWebpackPlugin({
49
+ authToken: process.env.SENTRY_AUTH_TOKEN,
50
+ org: "${options.orgSlug}",
51
+ project: "${options.projectSlug}",${
52
+ options.selfHosted ? `\n url: "${options.url}",` : ''
53
+ }
54
+ }),`)}
78
55
  ],
79
- }
80
- `;
56
+ }`),
57
+ );
81
58
 
82
59
  export const configureWebPackPlugin: SourceMapUploadToolConfigurationFunction =
83
60
  async (options) => {