@sentry/wizard 3.36.0 → 3.38.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 (49) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/e2e-tests/tests/nuxt-3.test.js +7 -13
  3. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  4. package/dist/e2e-tests/tests/nuxt-4.test.js +7 -13
  5. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  6. package/dist/package.json +2 -2
  7. package/dist/src/nuxt/nuxt-wizard.js +27 -20
  8. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  9. package/dist/src/nuxt/sdk-setup.d.ts +6 -2
  10. package/dist/src/nuxt/sdk-setup.js +107 -43
  11. package/dist/src/nuxt/sdk-setup.js.map +1 -1
  12. package/dist/src/nuxt/templates.d.ts +1 -1
  13. package/dist/src/nuxt/templates.js +5 -3
  14. package/dist/src/nuxt/templates.js.map +1 -1
  15. package/dist/src/nuxt/types.d.ts +2 -0
  16. package/dist/src/nuxt/types.js +10 -0
  17. package/dist/src/nuxt/types.js.map +1 -0
  18. package/dist/src/nuxt/utils.js +42 -6
  19. package/dist/src/nuxt/utils.js.map +1 -1
  20. package/dist/src/react-native/javascript.js +1 -1
  21. package/dist/src/react-native/javascript.js.map +1 -1
  22. package/dist/src/react-native/react-native-wizard.d.ts +5 -4
  23. package/dist/src/react-native/react-native-wizard.js +65 -41
  24. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  25. package/dist/src/utils/clack-utils.d.ts +5 -0
  26. package/dist/src/utils/clack-utils.js +15 -3
  27. package/dist/src/utils/clack-utils.js.map +1 -1
  28. package/dist/test/nuxt/templates.test.js +10 -1
  29. package/dist/test/nuxt/templates.test.js.map +1 -1
  30. package/dist/test/react-native/javascript.test.js +1 -1
  31. package/dist/test/react-native/javascript.test.js.map +1 -1
  32. package/e2e-tests/test-applications/nuxt-4-test-app/README.md +75 -0
  33. package/e2e-tests/test-applications/nuxt-4-test-app/nuxt.config.ts +6 -0
  34. package/e2e-tests/test-applications/nuxt-4-test-app/package.json +18 -0
  35. package/e2e-tests/test-applications/nuxt-4-test-app/public/favicon.ico +0 -0
  36. package/e2e-tests/test-applications/nuxt-4-test-app/public/robots.txt +1 -0
  37. package/e2e-tests/tests/nuxt-3.test.ts +6 -9
  38. package/e2e-tests/tests/nuxt-4.test.ts +6 -9
  39. package/package.json +2 -2
  40. package/src/nuxt/nuxt-wizard.ts +12 -4
  41. package/src/nuxt/sdk-setup.ts +136 -37
  42. package/src/nuxt/templates.ts +15 -8
  43. package/src/nuxt/types.ts +8 -0
  44. package/src/nuxt/utils.ts +17 -7
  45. package/src/react-native/javascript.ts +1 -1
  46. package/src/react-native/react-native-wizard.ts +32 -12
  47. package/src/utils/clack-utils.ts +13 -1
  48. package/test/nuxt/templates.test.ts +33 -6
  49. package/test/react-native/javascript.test.ts +1 -1
@@ -44,32 +44,29 @@ async function runWizardOnNuxtProject(projectDir: string): Promise<void> {
44
44
  'Please select your package manager.',
45
45
  );
46
46
 
47
- const nitropackOverridePrompted =
47
+ const nftOverridePrompted =
48
48
  packageManagerPrompted &&
49
49
  (await wizardInstance.sendStdinAndWaitForOutput(
50
50
  // Selecting `yarn` as the package manager
51
51
  [KEYS.DOWN, KEYS.ENTER],
52
- // Do you want to install version 2.9.7 of nitropack and add an override to package.json?
53
- 'Do you want to add an override for nitropack version ~2.9.7?',
52
+ 'Do you want to add an override for @vercel/nft version ^0.27.4?',
54
53
  {
55
54
  timeout: 240_000,
56
55
  },
57
56
  ));
58
57
 
59
- const nftOverridePrompted =
60
- nitropackOverridePrompted &&
58
+ const deploymentPlatformPrompted =
59
+ nftOverridePrompted &&
61
60
  (await wizardInstance.sendStdinAndWaitForOutput(
62
- // Selecting `yes` to downgrade nitropack
63
61
  KEYS.ENTER,
64
- 'Do you want to add an override for @vercel/nft version ^0.27.4?',
65
- // 'Do you want to install version',
62
+ 'Please select your deployment platform.',
66
63
  {
67
64
  timeout: 240_000,
68
65
  },
69
66
  ));
70
67
 
71
68
  const tracingOptionPrompted =
72
- nftOverridePrompted &&
69
+ deploymentPlatformPrompted &&
73
70
  (await wizardInstance.sendStdinAndWaitForOutput(
74
71
  KEYS.ENTER,
75
72
  // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
@@ -43,32 +43,29 @@ async function runWizardOnNuxtProject(projectDir: string): Promise<void> {
43
43
  'Please select your package manager.',
44
44
  );
45
45
 
46
- const nitropackOverridePrompted =
46
+ const nftOverridePrompted =
47
47
  packageManagerPrompted &&
48
48
  (await wizardInstance.sendStdinAndWaitForOutput(
49
49
  // Selecting `yarn` as the package manager
50
50
  [KEYS.DOWN, KEYS.ENTER],
51
- // Do you want to install version 2.9.7 of nitropack and add an override to package.json?
52
- 'Do you want to add an override for nitropack version ~2.9.7?',
51
+ 'Do you want to add an override for @vercel/nft version ^0.27.4?',
53
52
  {
54
53
  timeout: 240_000,
55
54
  },
56
55
  ));
57
56
 
58
- const nftOverridePrompted =
59
- nitropackOverridePrompted &&
57
+ const deploymentPlatformPrompted =
58
+ nftOverridePrompted &&
60
59
  (await wizardInstance.sendStdinAndWaitForOutput(
61
- // Selecting `yes` to downgrade nitropack
62
60
  KEYS.ENTER,
63
- 'Do you want to add an override for @vercel/nft version ^0.27.4?',
64
- // 'Do you want to install version',
61
+ 'Please select your deployment platform.',
65
62
  {
66
63
  timeout: 240_000,
67
64
  },
68
65
  ));
69
66
 
70
67
  const tracingOptionPrompted =
71
- nftOverridePrompted &&
68
+ deploymentPlatformPrompted &&
72
69
  (await wizardInstance.sendStdinAndWaitForOutput(
73
70
  KEYS.ENTER,
74
71
  // "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/wizard",
3
- "version": "3.36.0",
3
+ "version": "3.38.0",
4
4
  "homepage": "https://github.com/getsentry/sentry-wizard",
5
5
  "repository": "https://github.com/getsentry/sentry-wizard",
6
6
  "description": "Sentry wizard helping you to configure your project",
@@ -29,7 +29,7 @@
29
29
  "@sentry/node": "^7.119.2",
30
30
  "axios": "1.7.4",
31
31
  "chalk": "^2.4.1",
32
- "glob": "^8.1.0",
32
+ "glob": "9.3.5",
33
33
  "inquirer": "^6.2.0",
34
34
  "lodash": "^4.17.15",
35
35
  "magicast": "^0.2.10",
@@ -26,6 +26,8 @@ import {
26
26
  getNuxtConfig,
27
27
  createConfigFiles,
28
28
  addNuxtOverrides,
29
+ askDeploymentPlatform,
30
+ confirmReadImportDocs,
29
31
  } from './sdk-setup';
30
32
  import {
31
33
  createExampleComponent,
@@ -93,7 +95,7 @@ export async function runNuxtWizardWithTelemetry(
93
95
 
94
96
  const packageManager = await getPackageManager();
95
97
 
96
- await addNuxtOverrides(packageManager, minVer);
98
+ await addNuxtOverrides(packageJson, packageManager, minVer);
97
99
 
98
100
  const sdkAlreadyInstalled = hasPackageInstalled('@sentry/nuxt', packageJson);
99
101
  Sentry.setTag('sdk-already-installed', sdkAlreadyInstalled);
@@ -116,8 +118,11 @@ export async function runNuxtWizardWithTelemetry(
116
118
  selfHosted,
117
119
  };
118
120
 
121
+ const deploymentPlatform = await askDeploymentPlatform();
122
+ Sentry.setTag('deployment-platform', deploymentPlatform);
123
+
119
124
  await traceStep('configure-sdk', async () => {
120
- await addSDKModule(nuxtConfig, projectData);
125
+ await addSDKModule(nuxtConfig, projectData, deploymentPlatform);
121
126
  await createConfigFiles(selectedProject.keys[0].dsn.public);
122
127
  });
123
128
 
@@ -148,6 +153,8 @@ export async function runNuxtWizardWithTelemetry(
148
153
 
149
154
  await runPrettierIfInstalled();
150
155
 
156
+ await confirmReadImportDocs(deploymentPlatform);
157
+
151
158
  clack.outro(
152
159
  buildOutroMessage(shouldCreateExamplePage, shouldCreateExampleButton),
153
160
  );
@@ -170,8 +177,9 @@ function buildOutroMessage(
170
177
  )} component to a page and triggering it.`;
171
178
  }
172
179
 
173
- msg += `\n\nCheck out the SDK documentation for further configuration:
174
- https://docs.sentry.io/platforms/javascript/guides/nuxt/`;
180
+ msg += `\n\nCheck out the SDK documentation for further configuration: ${chalk.underline(
181
+ 'https://docs.sentry.io/platforms/javascript/guides/nuxt/',
182
+ )}`;
175
183
 
176
184
  return msg;
177
185
  }
@@ -1,10 +1,10 @@
1
1
  // @ts-expect-error - 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 * as Sentry from '@sentry/node';
4
4
  import chalk from 'chalk';
5
5
  import fs from 'fs';
6
6
  // @ts-expect-error - magicast is ESM and TS complains about that. It works though
7
- import { loadFile, generateCode, MagicastError } from 'magicast';
7
+ import { loadFile, generateCode } from 'magicast';
8
8
  // @ts-expect-error - magicast is ESM and TS complains about that. It works though
9
9
  import { addNuxtModule } from 'magicast/helpers';
10
10
  import path from 'path';
@@ -15,15 +15,19 @@ import {
15
15
  getSentryConfigContents,
16
16
  } from './templates';
17
17
  import {
18
- abort,
19
18
  abortIfCancelled,
20
19
  askShouldAddPackageOverride,
20
+ askShouldInstallPackage,
21
21
  featureSelectionPrompt,
22
+ installPackage,
22
23
  isUsingTypeScript,
24
+ opn,
23
25
  } from '../utils/clack-utils';
24
26
  import { traceStep } from '../telemetry';
25
27
  import { lt, SemVer } from 'semver';
26
- import { PackageManager } from '../utils/package-manager';
28
+ import { PackageManager, PNPM } from '../utils/package-manager';
29
+ import { hasPackageInstalled, PackageDotJson } from '../utils/package-json';
30
+ import { deploymentPlatforms, DeploymentPlatform } from './types';
27
31
 
28
32
  const possibleNuxtConfig = [
29
33
  'nuxt.config.js',
@@ -57,10 +61,40 @@ export async function getNuxtConfig(): Promise<string> {
57
61
  return path.join(process.cwd(), configFile);
58
62
  }
59
63
 
64
+ export async function askDeploymentPlatform(): Promise<
65
+ DeploymentPlatform | symbol
66
+ > {
67
+ return await abortIfCancelled(
68
+ clack.select({
69
+ message: 'Please select your deployment platform.',
70
+ options: deploymentPlatforms.map((platform) => ({
71
+ value: platform,
72
+ label: `${platform.charAt(0).toUpperCase()}${platform.slice(1)}`,
73
+ })),
74
+ }),
75
+ );
76
+ }
77
+
60
78
  export async function addSDKModule(
61
79
  config: string,
62
80
  options: { org: string; project: string; url: string; selfHosted: boolean },
81
+ deploymentPlatform: DeploymentPlatform | symbol,
63
82
  ): Promise<void> {
83
+ const shouldTopLevelImport =
84
+ deploymentPlatform === 'vercel' || deploymentPlatform === 'netlify';
85
+
86
+ if (shouldTopLevelImport) {
87
+ clack.log.warn(
88
+ `Sentry needs to be initialized before the application starts. ${chalk.cyan(
89
+ `${deploymentPlatform
90
+ .charAt(0)
91
+ .toUpperCase()}${deploymentPlatform.slice(1)}`,
92
+ )} does not support this yet.\n\nWe will inject the Sentry server-side config at the top of your Nuxt server entry file instead.\n\nThis comes with some restrictions, for more info see:\n\n${chalk.underline(
93
+ 'https://docs.sentry.io/platforms/javascript/guides/nuxt/install/top-level-import/',
94
+ )} `,
95
+ );
96
+ }
97
+
64
98
  try {
65
99
  const mod = await loadFile(config);
66
100
 
@@ -70,6 +104,9 @@ export async function addSDKModule(
70
104
  project: options.project,
71
105
  ...(options.selfHosted && { url: options.url }),
72
106
  },
107
+ ...(shouldTopLevelImport && {
108
+ autoInjectServerSentry: 'top-level-import',
109
+ }),
73
110
  });
74
111
  addNuxtModule(mod, '@sentry/nuxt/module', 'sourcemap', {
75
112
  client: 'hidden',
@@ -83,33 +120,31 @@ export async function addSDKModule(
83
120
  `Added Sentry Nuxt Module to ${chalk.cyan(path.basename(config))}.`,
84
121
  );
85
122
  } catch (e: unknown) {
86
- // Cases where users spread options are not covered by magicast,
87
- // so we fall back to showing how to configure the nuxt config
88
- // manually.
89
- if (e instanceof MagicastError) {
90
- clack.log.warn(
91
- `Automatic configuration of ${chalk.cyan(
92
- path.basename(config),
93
- )} failed, please add the following settings:`,
94
- );
95
- // eslint-disable-next-line no-console
96
- console.log(`\n\n${getNuxtModuleFallbackTemplate(options)}\n\n`);
97
- } else {
98
- clack.log.error(
99
- 'Error while adding the Sentry Nuxt Module to the Nuxt config.',
100
- );
101
- clack.log.info(
102
- chalk.dim(
103
- typeof e === 'object' && e != null && 'toString' in e
104
- ? e.toString()
105
- : typeof e === 'string'
106
- ? e
107
- : 'Unknown error',
108
- ),
109
- );
110
- Sentry.captureException('Error while setting up the Nuxt SDK');
111
- await abort('Exiting Wizard');
112
- }
123
+ clack.log.error(
124
+ 'Error while adding the Sentry Nuxt Module to the Nuxt config.',
125
+ );
126
+ clack.log.info(
127
+ chalk.dim(
128
+ typeof e === 'object' && e != null && 'toString' in e
129
+ ? e.toString()
130
+ : typeof e === 'string'
131
+ ? e
132
+ : 'Unknown error',
133
+ ),
134
+ );
135
+ Sentry.captureException(
136
+ 'Error while setting up the Nuxt Module in nuxt config',
137
+ );
138
+
139
+ clack.log.warn(
140
+ `Please add the following settings to ${chalk.cyan(
141
+ path.basename(config),
142
+ )}:`,
143
+ );
144
+ // eslint-disable-next-line no-console
145
+ console.log(
146
+ `\n\n${getNuxtModuleFallbackTemplate(options, shouldTopLevelImport)}\n\n`,
147
+ );
113
148
  }
114
149
  }
115
150
 
@@ -212,14 +247,13 @@ export async function createConfigFiles(dsn: string) {
212
247
  }
213
248
 
214
249
  export async function addNuxtOverrides(
250
+ packageJson: PackageDotJson,
215
251
  packageManager: PackageManager,
216
252
  nuxtMinVer: SemVer | null,
217
253
  ) {
254
+ const isPNPM = PNPM.detect();
255
+
218
256
  const overrides = [
219
- {
220
- pkgName: 'nitropack',
221
- pkgVersion: '~2.9.7',
222
- },
223
257
  {
224
258
  pkgName: '@vercel/nft',
225
259
  pkgVersion: '^0.27.4',
@@ -230,9 +264,17 @@ export async function addNuxtOverrides(
230
264
  ];
231
265
 
232
266
  clack.log.warn(
233
- `To ensure Sentry can properly instrument your code it needs to add version overrides for some Nuxt dependencies.\n\nFor more info see: ${chalk.cyan(
267
+ `To ensure Sentry can properly instrument your code it needs to add version overrides for some Nuxt dependencies${
268
+ isPNPM ? ` and install ${chalk.cyan('import-in-the-middle')}.` : '.'
269
+ }\n\nFor more info see: ${chalk.underline(
234
270
  'https://github.com/getsentry/sentry-javascript/issues/14514',
235
- )}`,
271
+ )}${
272
+ isPNPM
273
+ ? `\n\nand ${chalk.underline(
274
+ 'https://docs.sentry.io/platforms/javascript/guides/nuxt/troubleshooting/#pnpm-dev-cannot-find-package-import-in-the-middle',
275
+ )}`
276
+ : ''
277
+ }`,
236
278
  );
237
279
 
238
280
  for (const { pkgName, pkgVersion } of overrides) {
@@ -245,4 +287,61 @@ export async function addNuxtOverrides(
245
287
  await packageManager.addOverride(pkgName, pkgVersion);
246
288
  }
247
289
  }
290
+
291
+ if (PNPM.detect()) {
292
+ // For pnpm, we want to install iitm
293
+ // See: https://docs.sentry.io/platforms/javascript/guides/nuxt/troubleshooting/#pnpm-dev-cannot-find-package-import-in-the-middle
294
+ const iitmAlreadyInstalled = hasPackageInstalled(
295
+ 'import-in-the-middle',
296
+ packageJson,
297
+ );
298
+ Sentry.setTag('iitm-already-installed', iitmAlreadyInstalled);
299
+
300
+ const shouldInstallIitm = await askShouldInstallPackage(
301
+ 'import-in-the-middle',
302
+ );
303
+
304
+ if (shouldInstallIitm) {
305
+ await installPackage({
306
+ packageName: 'import-in-the-middle',
307
+ alreadyInstalled: iitmAlreadyInstalled,
308
+ packageManager,
309
+ });
310
+ }
311
+ }
312
+ }
313
+
314
+ export async function confirmReadImportDocs(
315
+ deploymentPlatform: DeploymentPlatform | symbol,
316
+ ) {
317
+ const canImportSentryServerConfigFile =
318
+ deploymentPlatform !== 'vercel' && deploymentPlatform !== 'netlify';
319
+
320
+ if (!canImportSentryServerConfigFile) {
321
+ // Nothing to do, users have been set up with automatic top-level-import instead
322
+ return;
323
+ }
324
+
325
+ const docsUrl =
326
+ 'https://docs.sentry.io/platforms/javascript/guides/nuxt/install/cli-import/#initializing-sentry-with---import';
327
+
328
+ clack.log.info(
329
+ `After building your Nuxt app, you need to ${chalk.bold(
330
+ '--import',
331
+ )} the Sentry server config file when running your app.\n\nFor more info, see:\n\n${chalk.underline(
332
+ docsUrl,
333
+ )}`,
334
+ );
335
+
336
+ const shouldOpenDocs = await abortIfCancelled(
337
+ clack.confirm({ message: 'Do you want to open the docs?' }),
338
+ );
339
+
340
+ Sentry.setTag('init-with-import-docs-opened', shouldOpenDocs);
341
+
342
+ if (shouldOpenDocs) {
343
+ opn(docsUrl, { wait: false }).catch(() => {
344
+ // opn throws in environments that don't have a browser (e.g. remote shells) so we just noop here
345
+ });
346
+ }
248
347
  }
@@ -14,12 +14,15 @@ export default defineNuxtConfig({
14
14
  `;
15
15
  }
16
16
 
17
- export function getNuxtModuleFallbackTemplate(options: {
18
- org: string;
19
- project: string;
20
- url: string;
21
- selfHosted: boolean;
22
- }): string {
17
+ export function getNuxtModuleFallbackTemplate(
18
+ options: {
19
+ org: string;
20
+ project: string;
21
+ url: string;
22
+ selfHosted: boolean;
23
+ },
24
+ shouldTopLevelImport: boolean,
25
+ ): string {
23
26
  return ` modules: ["@sentry/nuxt/module"],
24
27
  sentry: {
25
28
  sourceMapsUploadOptions: {
@@ -27,7 +30,11 @@ export function getNuxtModuleFallbackTemplate(options: {
27
30
  project: "${options.project}",${
28
31
  options.selfHosted ? `\n url: "${options.url}",` : ''
29
32
  }
30
- },
33
+ },${
34
+ shouldTopLevelImport
35
+ ? `\n autoInjectServerSentry: "top-level-import",`
36
+ : ''
37
+ }
31
38
  },
32
39
  sourcemap: { client: "hidden" },`;
33
40
  }
@@ -239,7 +246,7 @@ export function getSentryExampleApiTemplate() {
239
246
  // Feel free to delete this file.
240
247
  import { defineEventHandler } from '#imports';
241
248
 
242
- export default defineEventHandler(event => {
249
+ export default defineEventHandler(() => {
243
250
  throw new Error("Sentry Example API Route Error");
244
251
  });
245
252
  `;
@@ -0,0 +1,8 @@
1
+ export const deploymentPlatforms = [
2
+ 'vercel',
3
+ 'netlify',
4
+ 'other',
5
+ 'none',
6
+ ] as const;
7
+
8
+ export type DeploymentPlatform = (typeof deploymentPlatforms)[number];
package/src/nuxt/utils.ts CHANGED
@@ -1,6 +1,9 @@
1
+ // @ts-ignore - clack is ESM and TS complains about that. It works though
2
+ import * as clack from '@clack/prompts';
1
3
  import { gte, minVersion } from 'semver';
2
4
  // @ts-expect-error - magicast is ESM and TS complains about that. It works though
3
5
  import { loadFile } from 'magicast';
6
+ import { abortIfCancelled } from '../utils/clack-utils';
4
7
 
5
8
  export async function isNuxtV4(
6
9
  nuxtConfig: string,
@@ -18,14 +21,21 @@ export async function isNuxtV4(
18
21
  // At the time of writing, nuxt 4 is not on its own
19
22
  // major yet. We must read the `compatibilityVersion`
20
23
  // from the nuxt config.
21
- const mod = await loadFile(nuxtConfig);
22
- const config =
23
- mod.exports.default.$type === 'function-call'
24
- ? mod.exports.default.$args[0]
25
- : mod.exports.default;
24
+ try {
25
+ const mod = await loadFile(nuxtConfig);
26
+ const config =
27
+ mod.exports.default.$type === 'function-call'
28
+ ? mod.exports.default.$args[0]
29
+ : mod.exports.default;
26
30
 
27
- if (config && config.future && config.future.compatibilityVersion === 4) {
28
- return true;
31
+ if (config && config.future && config.future.compatibilityVersion === 4) {
32
+ return true;
33
+ }
34
+ } catch {
35
+ // If we cannot parse their config, just ask.
36
+ return await abortIfCancelled(
37
+ clack.confirm({ message: 'Are you using Nuxt version 4?' }),
38
+ );
29
39
  }
30
40
 
31
41
  return false;
@@ -98,6 +98,6 @@ Sentry.init({
98
98
  dsn: '${dsn}',
99
99
 
100
100
  // uncomment the line below to enable Spotlight (https://spotlightjs.com)
101
- // enableSpotlight: __DEV__,
101
+ // spotlight: __DEV__,
102
102
  });`;
103
103
  }
@@ -17,6 +17,7 @@ import {
17
17
  printWelcome,
18
18
  propertiesCliSetupConfig,
19
19
  runPrettierIfInstalled,
20
+ abort,
20
21
  } from '../utils/clack-utils';
21
22
  import { getPackageVersion, hasPackageInstalled } from '../utils/package-json';
22
23
  import { podInstall } from '../apple/cocoapod';
@@ -57,6 +58,7 @@ import { addExpoEnvLocal } from './expo-env-file';
57
58
  const xcode = require('xcode');
58
59
 
59
60
  export const RN_SDK_PACKAGE = '@sentry/react-native';
61
+ export const RN_SDK_SUPPORTED_RANGE = '>=5.0.0';
60
62
 
61
63
  export const RN_PACKAGE = 'react-native';
62
64
  export const RN_HUMAN_NAME = 'React Native';
@@ -68,21 +70,20 @@ export const SUPPORTED_EXPO_RANGE = '>=50.0.0';
68
70
  * The following SDK version ship with bundled Xcode scripts
69
71
  * which simplifies the Xcode Build Phases setup.
70
72
  */
71
- export const SDK_XCODE_SCRIPTS_SUPPORTED_SDK_RANGE = '>=5.11.0';
73
+ export const XCODE_SCRIPTS_SUPPORTED_SDK_RANGE = '>=5.11.0';
72
74
 
73
75
  /**
74
76
  * The following SDK version ship with Sentry Metro plugin
75
77
  */
76
- export const SDK_SENTRY_METRO_PLUGIN_SUPPORTED_SDK_RANGE = '>=5.11.0';
78
+ export const SENTRY_METRO_PLUGIN_SUPPORTED_SDK_RANGE = '>=5.11.0';
77
79
 
78
80
  /**
79
81
  * The following SDK version ship with bundled Expo plugin
80
82
  */
81
- export const SDK_EXPO_SUPPORTED_SDK_RANGE = `>=5.16.0`;
83
+ export const EXPO_SUPPORTED_SDK_RANGE = `>=5.16.0`;
82
84
 
83
85
  // The following SDK version shipped `withSentryConfig`
84
- export const SDK_SENTRY_METRO_WITH_SENTRY_CONFIG_SUPPORTED_SDK_RANGE =
85
- '>=5.17.0';
86
+ export const METRO_WITH_SENTRY_CONFIG_SUPPORTED_SDK_RANGE = '>=5.17.0';
86
87
 
87
88
  export type RNCliSetupConfigContent = Pick<
88
89
  Required<CliSetupConfigContent>,
@@ -151,6 +152,26 @@ Or setup using ${chalk.cyan(
151
152
  RN_SDK_PACKAGE,
152
153
  await getPackageDotJson(),
153
154
  );
155
+ if (sdkVersion) {
156
+ await confirmContinueIfPackageVersionNotSupported({
157
+ packageName: 'Sentry React Native SDK',
158
+ packageVersion: sdkVersion,
159
+ packageId: RN_SDK_PACKAGE,
160
+ acceptableVersions: RN_SDK_SUPPORTED_RANGE,
161
+ note: `Please upgrade to ${RN_SDK_SUPPORTED_RANGE} to continue with the wizard in this project.`,
162
+ });
163
+ } else {
164
+ const continueWithoutSdk = await abortIfCancelled(
165
+ clack.confirm({
166
+ message:
167
+ 'Could not detect Sentry React Native SDK version. Do you want to continue anyway?',
168
+ }),
169
+ );
170
+ if (!continueWithoutSdk) {
171
+ await abort(undefined, 0);
172
+ }
173
+ }
174
+ Sentry.setTag(`detected-sentry-react-native-sdk-version`, sdkVersion);
154
175
 
155
176
  const expoVersion = getPackageVersion('expo', packageJson);
156
177
  const isExpo = !!expoVersion;
@@ -159,8 +180,8 @@ Or setup using ${chalk.cyan(
159
180
  packageName: 'Sentry React Native SDK',
160
181
  packageVersion: sdkVersion,
161
182
  packageId: RN_SDK_PACKAGE,
162
- acceptableVersions: SDK_EXPO_SUPPORTED_SDK_RANGE,
163
- note: `Please upgrade to ${SDK_EXPO_SUPPORTED_SDK_RANGE} to continue with the wizard in this Expo project.`,
183
+ acceptableVersions: EXPO_SUPPORTED_SDK_RANGE,
184
+ note: `Please upgrade to ${EXPO_SUPPORTED_SDK_RANGE} to continue with the wizard in this Expo project.`,
164
185
  });
165
186
  await confirmContinueIfPackageVersionNotSupported({
166
187
  packageName: 'Expo SDK',
@@ -250,8 +271,7 @@ function addSentryToMetroConfig({
250
271
  sdkVersion &&
251
272
  fulfillsVersionRange({
252
273
  version: sdkVersion,
253
- acceptableVersions:
254
- SDK_SENTRY_METRO_WITH_SENTRY_CONFIG_SUPPORTED_SDK_RANGE,
274
+ acceptableVersions: METRO_WITH_SENTRY_CONFIG_SUPPORTED_SDK_RANGE,
255
275
  canBeLatest: true,
256
276
  })
257
277
  ) {
@@ -262,7 +282,7 @@ function addSentryToMetroConfig({
262
282
  sdkVersion &&
263
283
  fulfillsVersionRange({
264
284
  version: sdkVersion,
265
- acceptableVersions: SDK_SENTRY_METRO_PLUGIN_SUPPORTED_SDK_RANGE,
285
+ acceptableVersions: SENTRY_METRO_PLUGIN_SUPPORTED_SDK_RANGE,
266
286
  canBeLatest: true,
267
287
  })
268
288
  ) {
@@ -356,7 +376,7 @@ async function patchXcodeFiles(
356
376
  context.sdkVersion &&
357
377
  fulfillsVersionRange({
358
378
  version: context.sdkVersion,
359
- acceptableVersions: SDK_XCODE_SCRIPTS_SUPPORTED_SDK_RANGE,
379
+ acceptableVersions: XCODE_SCRIPTS_SUPPORTED_SDK_RANGE,
360
380
  canBeLatest: true,
361
381
  })
362
382
  ) {
@@ -381,7 +401,7 @@ async function patchXcodeFiles(
381
401
  context.sdkVersion &&
382
402
  fulfillsVersionRange({
383
403
  version: context.sdkVersion,
384
- acceptableVersions: SDK_XCODE_SCRIPTS_SUPPORTED_SDK_RANGE,
404
+ acceptableVersions: XCODE_SCRIPTS_SUPPORTED_SDK_RANGE,
385
405
  canBeLatest: true,
386
406
  })
387
407
  ) {
@@ -20,7 +20,7 @@ import {
20
20
  import { debug } from './debug';
21
21
  import { fulfillsVersionRange } from './semver';
22
22
 
23
- const opn = require('opn') as (
23
+ export const opn = require('opn') as (
24
24
  url: string,
25
25
  options?: {
26
26
  wait?: boolean;
@@ -1492,6 +1492,18 @@ export async function featureSelectionPrompt<F extends ReadonlyArray<Feature>>(
1492
1492
  });
1493
1493
  }
1494
1494
 
1495
+ export async function askShouldInstallPackage(
1496
+ pkgName: string,
1497
+ ): Promise<boolean> {
1498
+ return traceStep(`ask-install-package`, () =>
1499
+ abortIfCancelled(
1500
+ clack.confirm({
1501
+ message: `Do you want to install ${chalk.cyan(pkgName)}?`,
1502
+ }),
1503
+ ),
1504
+ );
1505
+ }
1506
+
1495
1507
  export async function askShouldAddPackageOverride(
1496
1508
  pkgName: string,
1497
1509
  pkgVersion: string,