@sentry/wizard 3.3.2 → 3.5.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 (71) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/bin.ts +29 -19
  3. package/dist/bin.js +23 -18
  4. package/dist/bin.js.map +1 -1
  5. package/dist/lib/Helper/Wizard.js +0 -9
  6. package/dist/lib/Helper/Wizard.js.map +1 -1
  7. package/dist/lib/Setup.js.map +1 -1
  8. package/dist/lib/Steps/ChooseIntegration.js +26 -10
  9. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  10. package/dist/lib/Steps/Integrations/{NextJs.d.ts → NextJsShim.d.ts} +1 -1
  11. package/dist/lib/Steps/Integrations/{NextJs.js → NextJsShim.js} +13 -10
  12. package/dist/lib/Steps/Integrations/NextJsShim.js.map +1 -0
  13. package/dist/lib/Steps/Integrations/SourceMapsShim.js +4 -1
  14. package/dist/lib/Steps/Integrations/SourceMapsShim.js.map +1 -1
  15. package/dist/lib/Steps/Integrations/{SvelteKit.d.ts → SvelteKitShim.d.ts} +1 -1
  16. package/dist/lib/Steps/Integrations/{SvelteKit.js → SvelteKitShim.js} +13 -10
  17. package/dist/lib/Steps/Integrations/SvelteKitShim.js.map +1 -0
  18. package/dist/package.json +3 -3
  19. package/dist/src/nextjs/nextjs-wizard.d.ts +2 -5
  20. package/dist/src/nextjs/nextjs-wizard.js +1 -1
  21. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  22. package/dist/src/sourcemaps/sourcemaps-wizard.d.ts +2 -5
  23. package/dist/src/sourcemaps/sourcemaps-wizard.js +68 -31
  24. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  25. package/dist/src/sourcemaps/tools/create-react-app.d.ts +1 -0
  26. package/dist/src/sourcemaps/tools/create-react-app.js +69 -0
  27. package/dist/src/sourcemaps/tools/create-react-app.js.map +1 -0
  28. package/dist/src/sourcemaps/tools/esbuild.d.ts +2 -0
  29. package/dist/src/sourcemaps/tools/esbuild.js +109 -0
  30. package/dist/src/sourcemaps/tools/esbuild.js.map +1 -0
  31. package/dist/src/sourcemaps/tools/rollup.d.ts +2 -0
  32. package/dist/src/sourcemaps/tools/rollup.js +109 -0
  33. package/dist/src/sourcemaps/tools/rollup.js.map +1 -0
  34. package/dist/src/sourcemaps/tools/sentry-cli.d.ts +2 -2
  35. package/dist/src/sourcemaps/tools/sentry-cli.js +111 -91
  36. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  37. package/dist/src/sourcemaps/tools/tsc.d.ts +1 -0
  38. package/dist/src/sourcemaps/tools/tsc.js +93 -0
  39. package/dist/src/sourcemaps/tools/tsc.js.map +1 -0
  40. package/dist/src/sourcemaps/utils/sdk-version.d.ts +14 -0
  41. package/dist/src/sourcemaps/utils/sdk-version.js +275 -0
  42. package/dist/src/sourcemaps/utils/sdk-version.js.map +1 -0
  43. package/dist/src/sveltekit/sveltekit-wizard.d.ts +2 -5
  44. package/dist/src/sveltekit/sveltekit-wizard.js +1 -1
  45. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  46. package/dist/src/utils/clack-utils.d.ts +13 -2
  47. package/dist/src/utils/clack-utils.js +78 -45
  48. package/dist/src/utils/clack-utils.js.map +1 -1
  49. package/dist/src/utils/types.d.ts +12 -0
  50. package/dist/src/utils/types.js +3 -0
  51. package/dist/src/utils/types.js.map +1 -0
  52. package/lib/Helper/Wizard.ts +0 -9
  53. package/lib/Setup.ts +1 -0
  54. package/lib/Steps/ChooseIntegration.ts +35 -11
  55. package/lib/Steps/Integrations/{NextJs.ts → NextJsShim.ts} +5 -2
  56. package/lib/Steps/Integrations/SourceMapsShim.ts +4 -1
  57. package/lib/Steps/Integrations/{SvelteKit.ts → SvelteKitShim.ts} +5 -2
  58. package/package.json +3 -3
  59. package/src/nextjs/nextjs-wizard.ts +3 -8
  60. package/src/sourcemaps/sourcemaps-wizard.ts +67 -38
  61. package/src/sourcemaps/tools/create-react-app.ts +19 -0
  62. package/src/sourcemaps/tools/esbuild.ts +65 -0
  63. package/src/sourcemaps/tools/rollup.ts +69 -0
  64. package/src/sourcemaps/tools/sentry-cli.ts +114 -105
  65. package/src/sourcemaps/tools/tsc.ts +39 -0
  66. package/src/sourcemaps/utils/sdk-version.ts +264 -0
  67. package/src/sveltekit/sveltekit-wizard.ts +3 -6
  68. package/src/utils/clack-utils.ts +71 -29
  69. package/src/utils/types.ts +13 -0
  70. package/dist/lib/Steps/Integrations/NextJs.js.map +0 -1
  71. package/dist/lib/Steps/Integrations/SvelteKit.js.map +0 -1
@@ -0,0 +1,65 @@
1
+ // @ts-ignore - clack is ESM and TS complains about that. It works though
2
+ import clack, { select } from '@clack/prompts';
3
+ import chalk from 'chalk';
4
+ import {
5
+ abortIfCancelled,
6
+ addDotEnvSentryBuildPluginFile,
7
+ getPackageDotJson,
8
+ hasPackageInstalled,
9
+ installPackage,
10
+ } from '../../utils/clack-utils';
11
+
12
+ import {
13
+ SourceMapUploadToolConfigurationFunction,
14
+ SourceMapUploadToolConfigurationOptions,
15
+ } from './types';
16
+
17
+ const getCodeSnippet = (options: SourceMapUploadToolConfigurationOptions) =>
18
+ chalk.gray(`
19
+ ${chalk.greenBright(
20
+ 'const { sentryEsbuildPlugin } = require("@sentry/esbuild-plugin");',
21
+ )}
22
+
23
+ require("esbuild").build({
24
+ ${chalk.greenBright(
25
+ 'sourcemap: true, // Source map generation must be turned on',
26
+ )}
27
+ plugins: [
28
+ // Put the Sentry esbuild plugin after all other plugins
29
+ ${chalk.greenBright(`sentryEsbuildPlugin({
30
+ authToken: process.env.SENTRY_AUTH_TOKEN,
31
+ org: "${options.orgSlug}",
32
+ project: "${options.projectSlug}",${
33
+ options.selfHosted ? `\n url: "${options.url}",` : ''
34
+ }
35
+ }),`)}
36
+ ],
37
+ });
38
+ `);
39
+
40
+ export const configureEsbuildPlugin: SourceMapUploadToolConfigurationFunction =
41
+ async (options) => {
42
+ await installPackage({
43
+ packageName: '@sentry/esbuild-plugin',
44
+ alreadyInstalled: hasPackageInstalled(
45
+ '@sentry/esbuild-plugin',
46
+ await getPackageDotJson(),
47
+ ),
48
+ });
49
+
50
+ clack.log.step(`Add the following code to your esbuild config:`);
51
+
52
+ // Intentially logging directly to console here so that the code can be copied/pasted directly
53
+ // eslint-disable-next-line no-console
54
+ console.log(getCodeSnippet(options));
55
+
56
+ await abortIfCancelled(
57
+ select({
58
+ message: 'Did you copy the snippet above?',
59
+ options: [{ label: 'Yes, continue!', value: true }],
60
+ initialValue: true,
61
+ }),
62
+ );
63
+
64
+ await addDotEnvSentryBuildPluginFile(options.authToken);
65
+ };
@@ -0,0 +1,69 @@
1
+ // @ts-ignore - clack is ESM and TS complains about that. It works though
2
+ import clack, { select } from '@clack/prompts';
3
+ import chalk from 'chalk';
4
+ import {
5
+ abortIfCancelled,
6
+ addDotEnvSentryBuildPluginFile,
7
+ getPackageDotJson,
8
+ hasPackageInstalled,
9
+ installPackage,
10
+ } from '../../utils/clack-utils';
11
+
12
+ import {
13
+ SourceMapUploadToolConfigurationFunction,
14
+ SourceMapUploadToolConfigurationOptions,
15
+ } from './types';
16
+
17
+ const getCodeSnippet = (options: SourceMapUploadToolConfigurationOptions) =>
18
+ chalk.gray(`
19
+ ${chalk.greenBright(
20
+ 'import { sentryRollupPlugin } from "@sentry/rollup-plugin";',
21
+ )}
22
+
23
+ export default {
24
+ output: {
25
+ ${chalk.greenBright(
26
+ 'sourcemap: true, // Source map generation must be turned on',
27
+ )}
28
+ },
29
+ plugins: [
30
+ // Put the Sentry rollup plugin after all other plugins
31
+ ${chalk.greenBright(`sentryRollupPlugin({
32
+ authToken: process.env.SENTRY_AUTH_TOKEN,
33
+ org: "${options.orgSlug}",
34
+ project: "${options.projectSlug}",${
35
+ options.selfHosted ? `\n url: "${options.url}",` : ''
36
+ }
37
+ }),`)}
38
+ ],
39
+ };
40
+ `);
41
+
42
+ export const configureRollupPlugin: SourceMapUploadToolConfigurationFunction =
43
+ async (options) => {
44
+ await installPackage({
45
+ packageName: '@sentry/rollup-plugin',
46
+ alreadyInstalled: hasPackageInstalled(
47
+ '@sentry/rollup-plugin',
48
+ await getPackageDotJson(),
49
+ ),
50
+ });
51
+
52
+ clack.log.step(
53
+ `Add the following code to your rollup config:`,
54
+ );
55
+
56
+ // Intentially logging directly to console here so that the code can be copied/pasted directly
57
+ // eslint-disable-next-line no-console
58
+ console.log(getCodeSnippet(options));
59
+
60
+ await abortIfCancelled(
61
+ select({
62
+ message: 'Did you copy the snippet above?',
63
+ options: [{ label: 'Yes, continue!', value: true }],
64
+ initialValue: true,
65
+ }),
66
+ );
67
+
68
+ await addDotEnvSentryBuildPluginFile(options.authToken);
69
+ };
@@ -12,117 +12,126 @@ import {
12
12
  installPackage,
13
13
  } from '../../utils/clack-utils';
14
14
 
15
- import { SourceMapUploadToolConfigurationFunction } from './types';
16
-
17
- export const configureSentryCLI: SourceMapUploadToolConfigurationFunction =
18
- async (options) => {
19
- const packageDotJson = await getPackageDotJson();
20
-
21
- await installPackage({
22
- packageName: '@sentry/cli',
23
- alreadyInstalled: hasPackageInstalled('@sentry/cli', packageDotJson),
24
- });
25
-
26
- let validPath = false;
27
- let relativeArtifactPath;
28
- do {
29
- const rawArtifactPath = await abortIfCancelled(
30
- clack.text({
31
- message: 'Where are your build artifacts located?',
32
- placeholder: `.${path.sep}out`,
33
- }),
34
- );
35
-
36
- if (path.isAbsolute(rawArtifactPath)) {
37
- relativeArtifactPath = path.relative(process.cwd(), rawArtifactPath);
38
- } else {
39
- relativeArtifactPath = rawArtifactPath;
40
- }
41
-
42
- try {
43
- await fs.promises.access(
44
- path.join(process.cwd(), relativeArtifactPath),
45
- );
46
- validPath = true;
47
- } catch {
48
- validPath = await abortIfCancelled(
49
- clack.select({
50
- message: `We couldn't find artifacts at ${relativeArtifactPath}. Are you sure that this is the location that contains your build artifacts?`,
51
- options: [
52
- {
53
- label: 'No, let me verify.',
54
- value: false,
55
- },
56
- { label: 'Yes, I am sure!', value: true },
57
- ],
58
- initialValue: false,
59
- }),
60
- );
61
- }
62
- } while (!validPath);
63
-
64
- const relativePosixArtifactPath = relativeArtifactPath
65
- .split(path.sep)
66
- .join(path.posix.sep);
67
-
68
- await abortIfCancelled(
69
- clack.select({
70
- message: `Verify that your build tool is generating source maps. ${chalk.dim(
71
- '(Your build output folder should contain .js.map files after a build)',
72
- )}`,
73
- options: [{ label: 'I checked. Continue!', value: true }],
74
- initialValue: true,
75
- }),
76
- );
15
+ import { SourceMapUploadToolConfigurationOptions } from './types';
77
16
 
78
- packageDotJson.scripts = packageDotJson.scripts || {};
79
- packageDotJson.scripts['sentry:ci'] = `sentry-cli sourcemaps inject --org ${
80
- options.orgSlug
81
- } --project ${
82
- options.projectSlug
83
- } ${relativePosixArtifactPath} && sentry-cli${
84
- options.selfHosted ? ` --url ${options.url}` : ''
85
- } sourcemaps upload --org ${options.orgSlug} --project ${
86
- options.projectSlug
87
- } ${relativePosixArtifactPath}`;
88
-
89
- await fs.promises.writeFile(
90
- path.join(process.cwd(), 'package.json'),
91
- JSON.stringify(packageDotJson, null, 2),
92
- );
17
+ export async function configureSentryCLI(
18
+ options: SourceMapUploadToolConfigurationOptions,
19
+ configureSourcemapGenerationFlow: () => Promise<void> = defaultConfigureSourcemapGenerationFlow,
20
+ ): Promise<void> {
21
+ const packageDotJson = await getPackageDotJson();
93
22
 
94
- clack.log.info(
95
- `Added a ${chalk.cyan('sentry:ci')} script to your ${chalk.cyan(
96
- 'package.json',
97
- )}. Make sure to run this script ${chalk.bold(
98
- 'after',
99
- )} building your application but ${chalk.bold('before')} deploying!`,
100
- );
23
+ await installPackage({
24
+ packageName: '@sentry/cli',
25
+ alreadyInstalled: hasPackageInstalled('@sentry/cli', packageDotJson),
26
+ });
101
27
 
102
- const addedToCI = await abortIfCancelled(
103
- clack.select({
104
- message: `Did you add running the ${chalk.cyan(
105
- 'sentry:ci',
106
- )} script to your CI pipeline ${chalk.bold('after the build step')}?`,
107
- options: [
108
- { label: 'Yes, continue!', value: true },
109
- {
110
- label: "I'll do it later...",
111
- value: false,
112
- hint: chalk.yellow(
113
- 'You need to run the command after each build for source maps to work properly.',
114
- ),
115
- },
116
- ],
117
- initialValue: true,
28
+ let validPath = false;
29
+ let relativeArtifactPath;
30
+ do {
31
+ const rawArtifactPath = await abortIfCancelled(
32
+ clack.text({
33
+ message: 'Where are your build artifacts located?',
34
+ placeholder: `.${path.sep}out`,
35
+ validate(value) {
36
+ if (!value) {
37
+ return 'Please enter a path.';
38
+ }
39
+ },
118
40
  }),
119
41
  );
120
42
 
121
- Sentry.setTag('added-ci-script', addedToCI);
43
+ if (path.isAbsolute(rawArtifactPath)) {
44
+ relativeArtifactPath = path.relative(process.cwd(), rawArtifactPath);
45
+ } else {
46
+ relativeArtifactPath = rawArtifactPath;
47
+ }
122
48
 
123
- if (!addedToCI) {
124
- clack.log.info("Don't forget! :)");
49
+ try {
50
+ await fs.promises.access(path.join(process.cwd(), relativeArtifactPath));
51
+ validPath = true;
52
+ } catch {
53
+ validPath = await abortIfCancelled(
54
+ clack.select({
55
+ message: `We couldn't find artifacts at ${relativeArtifactPath}. Are you sure that this is the location that contains your build artifacts?`,
56
+ options: [
57
+ {
58
+ label: 'No, let me verify.',
59
+ value: false,
60
+ },
61
+ { label: 'Yes, I am sure!', value: true },
62
+ ],
63
+ initialValue: false,
64
+ }),
65
+ );
125
66
  }
67
+ } while (!validPath);
68
+
69
+ const relativePosixArtifactPath = relativeArtifactPath
70
+ .split(path.sep)
71
+ .join(path.posix.sep);
72
+
73
+ await configureSourcemapGenerationFlow();
74
+
75
+ packageDotJson.scripts = packageDotJson.scripts || {};
76
+ packageDotJson.scripts['sentry:ci'] = `sentry-cli sourcemaps inject --org ${
77
+ options.orgSlug
78
+ } --project ${
79
+ options.projectSlug
80
+ } ${relativePosixArtifactPath} && sentry-cli${
81
+ options.selfHosted ? ` --url ${options.url}` : ''
82
+ } sourcemaps upload --org ${options.orgSlug} --project ${
83
+ options.projectSlug
84
+ } ${relativePosixArtifactPath}`;
85
+
86
+ await fs.promises.writeFile(
87
+ path.join(process.cwd(), 'package.json'),
88
+ JSON.stringify(packageDotJson, null, 2),
89
+ );
90
+
91
+ clack.log.info(
92
+ `Added a ${chalk.cyan('sentry:ci')} script to your ${chalk.cyan(
93
+ 'package.json',
94
+ )}. Make sure to run this script ${chalk.bold(
95
+ 'after',
96
+ )} building your application but ${chalk.bold('before')} deploying!`,
97
+ );
98
+
99
+ const addedToCI = await abortIfCancelled(
100
+ clack.select({
101
+ message: `Did you add a step to your CI pipeline that runs the ${chalk.cyan(
102
+ 'sentry:ci',
103
+ )} script ${chalk.bold('right after')} building your application?`,
104
+ options: [
105
+ { label: 'Yes, continue!', value: true },
106
+ {
107
+ label: "I'll do it later...",
108
+ value: false,
109
+ hint: chalk.yellow(
110
+ 'You need to run the command after each build for source maps to work properly.',
111
+ ),
112
+ },
113
+ ],
114
+ initialValue: true,
115
+ }),
116
+ );
117
+
118
+ Sentry.setTag('added-ci-script', addedToCI);
119
+
120
+ if (!addedToCI) {
121
+ clack.log.info("Don't forget! :)");
122
+ }
123
+
124
+ await addSentryCliRc(options.authToken);
125
+ }
126
126
 
127
- await addSentryCliRc(options.authToken);
128
- };
127
+ async function defaultConfigureSourcemapGenerationFlow(): Promise<void> {
128
+ await abortIfCancelled(
129
+ clack.select({
130
+ message: `Verify that your build tool is generating source maps. ${chalk.dim(
131
+ '(Your build output folder should contain .js.map files after a build)',
132
+ )}`,
133
+ options: [{ label: 'I checked. Continue!', value: true }],
134
+ initialValue: true,
135
+ }),
136
+ );
137
+ }
@@ -0,0 +1,39 @@
1
+ // @ts-ignore - clack is ESM and TS complains about that. It works though
2
+ import clack, { select } from '@clack/prompts';
3
+ 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
+
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);
18
+
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
+
28
+ const codeSnippet = chalk.gray(`
29
+ {
30
+ "compilerOptions": {
31
+ ${chalk.greenBright('"sourceMap": true,')}
32
+ ${chalk.greenBright('"inlineSources": true,')}
33
+
34
+ // Set \`sourceRoot\` to "/" to strip the build path prefix from
35
+ // generated source code references. This will improve issue grouping in Sentry.
36
+ ${chalk.greenBright('"sourceRoot": "/"')}
37
+ }
38
+ }
39
+ `);
@@ -0,0 +1,264 @@
1
+ // @ts-ignore - clack is ESM and TS complains about that. It works though
2
+ import clack from '@clack/prompts';
3
+ import chalk from 'chalk';
4
+ import { minVersion, satisfies } from 'semver';
5
+ import {
6
+ abortIfCancelled,
7
+ getPackageDotJson,
8
+ getPackageVersion,
9
+ installPackage,
10
+ } from '../../utils/clack-utils';
11
+
12
+ import * as Sentry from '@sentry/node';
13
+
14
+ const MINIMUM_DEBUG_ID_SDK_VERSION = '7.47.0';
15
+
16
+ // This array is orderd by the SDKs we want to check for first.
17
+ // The reason is that some SDKs depend on others and some users might
18
+ // have added the dependencies to their package.json. We want to make sure
19
+ // that we actually detect the "top-level" SDK first.
20
+ const SENTRY_SDK_PACKAGE_NAMES = [
21
+ // SDKs using other framework SDKs need to be checked first
22
+ '@sentry/gatsby',
23
+ '@sentry/nextjs',
24
+ '@sentry/remix',
25
+ '@sentry/sveltekit',
26
+
27
+ // Framework SDKs
28
+ '@sentry/angular',
29
+ '@sentry/angular-ivy',
30
+ '@sentry/ember',
31
+ '@sentry/react',
32
+ '@sentry/svelte',
33
+ '@sentry/vue',
34
+ '@sentry/serverless',
35
+
36
+ // Base SDKs
37
+ '@sentry/browser',
38
+ '@sentry/node',
39
+ ] as const;
40
+
41
+ type SdkPackage = {
42
+ name: (typeof SENTRY_SDK_PACKAGE_NAMES)[number];
43
+ version: string;
44
+ };
45
+
46
+ /**
47
+ * Check for a minimum SDK version and prompt the user to upgrade if necessary.
48
+ * We distinguish between 4 cases here:
49
+ *
50
+ * 1. Users didn't install any SDK yet
51
+ * -> We tell them to install an SDK and then continue with the wizard
52
+ * 2. Users installed an SDK in the range >=7.47.0
53
+ * -> All good, no need to do anything!
54
+ * 3. Users installed an SDK in the range >=7.0.0 <= 7.46.0
55
+ * -> We ask if they want to auto-update to the latest version
56
+ * 4. Users installed an SDK in the range <7.x
57
+ * -> We tell users to manually upgrade (migrate between majors)
58
+ */
59
+ export async function ensureMinimumSdkVersionIsInstalled(): Promise<void> {
60
+ const packageJson = await getPackageDotJson();
61
+
62
+ const installedSdkPackages = SENTRY_SDK_PACKAGE_NAMES.map((packageName) => ({
63
+ name: packageName,
64
+ version: getPackageVersion(packageName, packageJson),
65
+ })).filter((sdkPackage): sdkPackage is SdkPackage => !!sdkPackage.version);
66
+
67
+ const installedSdkPackage =
68
+ installedSdkPackages.length > 0 && installedSdkPackages[0];
69
+
70
+ // Case 1:
71
+ if (!installedSdkPackage) {
72
+ return await handleNoSdkInstalled();
73
+ }
74
+
75
+ const { name: installedSdkName, version: installedSdkVersionOrRange } =
76
+ installedSdkPackage;
77
+
78
+ const minInstalledVersion = getMinInstalledVersion(
79
+ installedSdkVersionOrRange,
80
+ installedSdkName,
81
+ );
82
+
83
+ if (!minInstalledVersion) {
84
+ // This is handled in the getMinInstalledVersion function
85
+ return;
86
+ }
87
+
88
+ const hasDebugIdCompatibleSdkVersion = satisfies(
89
+ minInstalledVersion,
90
+ `>=${MINIMUM_DEBUG_ID_SDK_VERSION}`,
91
+ );
92
+
93
+ // Case 2:
94
+ if (hasDebugIdCompatibleSdkVersion) {
95
+ Sentry.setTag('initial-sdk-version', '>=7.47.0');
96
+ return;
97
+ }
98
+
99
+ const hasV7SdkVersion = satisfies(minInstalledVersion, '>=7.0.0');
100
+
101
+ clack.log.warn(
102
+ `${chalk.yellowBright(
103
+ `It seems like you're using an outdated version (${installedSdkVersionOrRange}) of the ${chalk.bold(
104
+ installedSdkName,
105
+ )} SDK.`,
106
+ )}
107
+ Uploading source maps is easiest with an SDK from version ${chalk.bold(
108
+ MINIMUM_DEBUG_ID_SDK_VERSION,
109
+ )} or newer.
110
+ `,
111
+ );
112
+
113
+ // Case 3:
114
+ if (hasV7SdkVersion) {
115
+ await handleAutoUpdateSdk(installedSdkName);
116
+ return;
117
+ }
118
+
119
+ // Case 4:
120
+ await handleManuallyUpdateSdk(minInstalledVersion);
121
+ }
122
+
123
+ async function handleManuallyUpdateSdk(minInstalledVersion: string) {
124
+ Sentry.setTag(
125
+ 'initial-sdk-version',
126
+ `${satisfies(minInstalledVersion, '>=6.0.0') ? '6.x' : '<6.0.0'}`,
127
+ );
128
+
129
+ clack.log
130
+ .info(`When upgrading from a version older than 7.0.0, make sure to follow the migration guide:
131
+ https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md#upgrading-from-6x-to-7x
132
+ `);
133
+
134
+ const didUpdate = await abortIfCancelled(
135
+ clack.select({
136
+ message: 'Did you update your SDK to the latest version?',
137
+ options: [
138
+ {
139
+ label: 'Yes!',
140
+ value: true,
141
+ },
142
+ {
143
+ label: "No, I'll do it later...",
144
+ value: false,
145
+ hint: chalk.yellow(
146
+ `Remember to update your SDK to at least ${MINIMUM_DEBUG_ID_SDK_VERSION}.`,
147
+ ),
148
+ },
149
+ ],
150
+ initialValue: true,
151
+ }),
152
+ );
153
+
154
+ Sentry.setTag(
155
+ 'resolved-sdk-status',
156
+ didUpdate ? 'updated-manually' : 'update-later',
157
+ );
158
+ }
159
+
160
+ async function handleAutoUpdateSdk(packageName: string) {
161
+ Sentry.setTag('initial-sdk-version', '>=7.0.0 <7.47.0');
162
+
163
+ const shouldUpdate = await abortIfCancelled(
164
+ clack.select({
165
+ message:
166
+ 'Do you want to automatically update your SDK to the latest version?',
167
+ options: [
168
+ {
169
+ label: 'Yes!',
170
+ value: true,
171
+ hint: chalk.green('Recommended'),
172
+ },
173
+ {
174
+ label: "No, I'll do it later...",
175
+ value: false,
176
+ hint: chalk.yellow(
177
+ `Remember to update your SDK to at least ${MINIMUM_DEBUG_ID_SDK_VERSION}.`,
178
+ ),
179
+ },
180
+ ],
181
+ initialValue: true,
182
+ }),
183
+ );
184
+
185
+ if (shouldUpdate) {
186
+ await installPackage({
187
+ packageName,
188
+ alreadyInstalled: true,
189
+ askBeforeUpdating: false, // we already did this above
190
+ });
191
+ }
192
+
193
+ Sentry.setTag(
194
+ 'resolved-sdk-status',
195
+ shouldUpdate ? 'updated-automatically' : 'update-later',
196
+ );
197
+ }
198
+
199
+ async function handleNoSdkInstalled(): Promise<void> {
200
+ Sentry.setTag('initial-sdk-version', 'none');
201
+
202
+ clack.log.warn(
203
+ `${chalk.yellowBright(
204
+ `It seems like you didn't yet install a Sentry SDK in your project.`,
205
+ )}
206
+ We recommend setting up the SDK before continuing with the source maps wizard.
207
+
208
+ ${chalk.dim(`Take a look at our docs to get started:
209
+ https://docs.sentry.io/`)}`,
210
+ );
211
+
212
+ const installedSDK = await abortIfCancelled(
213
+ clack.select({
214
+ message: 'Did you set up your Sentry SDK?',
215
+ options: [
216
+ { label: 'Yes, continue!', value: true },
217
+ {
218
+ label: "I'll do it later...",
219
+ value: false,
220
+ hint: chalk.yellow(
221
+ 'You need to set up an SDK before you can use Sentry',
222
+ ),
223
+ },
224
+ ],
225
+ initialValue: true,
226
+ }),
227
+ );
228
+
229
+ Sentry.setTag(
230
+ 'resolved-sdk-status',
231
+ installedSDK ? 'installed-manually' : 'install-later',
232
+ );
233
+ }
234
+
235
+ function getMinInstalledVersion(
236
+ installedSdkVersionOrRange: string,
237
+ installedSdkName: string,
238
+ ): string | undefined {
239
+ try {
240
+ // If `minVersion` is unable to parse the version it will throw an error
241
+ // However, it will also return `null` if the parameter is undefined, which
242
+ // we explicitly checked before but the typing doesn't know that.
243
+ const minInstalledVersion = minVersion(installedSdkVersionOrRange)?.version;
244
+ if (minInstalledVersion) {
245
+ return minInstalledVersion;
246
+ }
247
+ } catch {
248
+ // handling this, along with the `null` case below
249
+ }
250
+
251
+ Sentry.setTag('initial-sdk-version', 'unknown');
252
+ clack.log.warn(
253
+ `${chalk.yellow(
254
+ `Could not parse the version of your installed SDK ("${installedSdkName}": "${installedSdkVersionOrRange}")`,
255
+ )}
256
+
257
+ Please make sure that your Sentry SDK is updated to version ${chalk.bold(
258
+ MINIMUM_DEBUG_ID_SDK_VERSION,
259
+ )} or newer.
260
+ `,
261
+ );
262
+
263
+ return undefined;
264
+ }
@@ -13,17 +13,14 @@ import {
13
13
  installPackage,
14
14
  printWelcome,
15
15
  } from '../utils/clack-utils';
16
+ import { WizardOptions } from '../utils/types';
16
17
  import { createExamplePage } from './sdk-example';
17
18
  import { createOrMergeSvelteKitFiles, loadSvelteConfig } from './sdk-setup';
18
19
 
19
20
  import { setupCLIConfig } from './sentry-cli-setup';
20
21
 
21
- interface SvelteKitWizardOptions {
22
- promoCode?: string;
23
- }
24
-
25
22
  export async function runSvelteKitWizard(
26
- options: SvelteKitWizardOptions,
23
+ options: WizardOptions,
27
24
  ): Promise<void> {
28
25
  printWelcome({
29
26
  wizardName: 'Sentry SvelteKit Wizard',
@@ -35,7 +32,7 @@ export async function runSvelteKitWizard(
35
32
  const packageJson = await getPackageDotJson();
36
33
  await ensurePackageIsInstalled(packageJson, '@sveltejs/kit', 'Sveltekit');
37
34
 
38
- const { url: sentryUrl, selfHosted } = await askForSelfHosted();
35
+ const { url: sentryUrl, selfHosted } = await askForSelfHosted(options.url);
39
36
 
40
37
  const { projects, apiKeys } = await askForWizardLogin({
41
38
  promoCode: options.promoCode,