@sentry/wizard 3.10.0 → 3.12.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 (150) hide show
  1. package/CHANGELOG.md +54 -7
  2. package/dist/lib/Constants.d.ts +1 -0
  3. package/dist/lib/Constants.js +5 -0
  4. package/dist/lib/Constants.js.map +1 -1
  5. package/dist/lib/Steps/ChooseIntegration.js +8 -4
  6. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  7. package/dist/lib/Steps/Integrations/Android.d.ts +9 -0
  8. package/dist/lib/Steps/Integrations/Android.js +86 -0
  9. package/dist/lib/Steps/Integrations/Android.js.map +1 -0
  10. package/dist/lib/Steps/Integrations/ReactNative.js +3 -3
  11. package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
  12. package/dist/lib/Steps/PromptForParameters.js +36 -3
  13. package/dist/lib/Steps/PromptForParameters.js.map +1 -1
  14. package/dist/lib/Steps/SentryProjectSelector.js +1 -1
  15. package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
  16. package/dist/package.json +4 -3
  17. package/dist/src/android/android-wizard.d.ts +2 -0
  18. package/dist/src/android/android-wizard.js +225 -0
  19. package/dist/src/android/android-wizard.js.map +1 -0
  20. package/dist/src/android/code-tools.d.ts +47 -0
  21. package/dist/src/android/code-tools.js +173 -0
  22. package/dist/src/android/code-tools.js.map +1 -0
  23. package/dist/src/android/gradle.d.ts +62 -0
  24. package/dist/src/android/gradle.js +286 -0
  25. package/dist/src/android/gradle.js.map +1 -0
  26. package/dist/src/android/manifest.d.ts +57 -0
  27. package/dist/src/android/manifest.js +183 -0
  28. package/dist/src/android/manifest.js.map +1 -0
  29. package/dist/src/android/templates.d.ts +11 -0
  30. package/dist/src/android/templates.js +34 -0
  31. package/dist/src/android/templates.js.map +1 -0
  32. package/dist/src/apple/apple-wizard.js +123 -64
  33. package/dist/src/apple/apple-wizard.js.map +1 -1
  34. package/dist/src/apple/cocoapod.js +4 -3
  35. package/dist/src/apple/cocoapod.js.map +1 -1
  36. package/dist/src/apple/code-tools.d.ts +1 -1
  37. package/dist/src/apple/code-tools.js +43 -19
  38. package/dist/src/apple/code-tools.js.map +1 -1
  39. package/dist/src/apple/fastlane.d.ts +1 -1
  40. package/dist/src/apple/fastlane.js +12 -6
  41. package/dist/src/apple/fastlane.js.map +1 -1
  42. package/dist/src/apple/templates.d.ts +2 -2
  43. package/dist/src/apple/templates.js +4 -4
  44. package/dist/src/apple/templates.js.map +1 -1
  45. package/dist/src/apple/xcode-manager.d.ts +19 -3
  46. package/dist/src/apple/xcode-manager.js +126 -24
  47. package/dist/src/apple/xcode-manager.js.map +1 -1
  48. package/dist/src/nextjs/nextjs-wizard.js +49 -11
  49. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  50. package/dist/src/nextjs/templates.d.ts +2 -0
  51. package/dist/src/nextjs/templates.js +6 -2
  52. package/dist/src/nextjs/templates.js.map +1 -1
  53. package/dist/src/remix/remix-wizard.js +10 -20
  54. package/dist/src/remix/remix-wizard.js.map +1 -1
  55. package/dist/src/sourcemaps/sourcemaps-wizard.js +26 -13
  56. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  57. package/dist/src/sourcemaps/tools/nextjs.js +1 -1
  58. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
  59. package/dist/src/sourcemaps/tools/sentry-cli.js +19 -16
  60. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  61. package/dist/src/sourcemaps/tools/vite.d.ts +2 -1
  62. package/dist/src/sourcemaps/tools/vite.js +123 -111
  63. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  64. package/dist/src/sourcemaps/tools/webpack.d.ts +6 -1
  65. package/dist/src/sourcemaps/tools/webpack.js +290 -25
  66. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  67. package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
  68. package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
  69. package/dist/src/sveltekit/sdk-setup.js +5 -5
  70. package/dist/src/sveltekit/sdk-setup.js.map +1 -1
  71. package/dist/src/sveltekit/sveltekit-wizard.js +34 -44
  72. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  73. package/dist/src/telemetry.js +1 -0
  74. package/dist/src/telemetry.js.map +1 -1
  75. package/dist/src/utils/ast-utils.d.ts +9 -5
  76. package/dist/src/utils/ast-utils.js +26 -11
  77. package/dist/src/utils/ast-utils.js.map +1 -1
  78. package/dist/src/utils/clack-utils.d.ts +74 -28
  79. package/dist/src/utils/clack-utils.js +427 -264
  80. package/dist/src/utils/clack-utils.js.map +1 -1
  81. package/dist/src/utils/package-manager.d.ts +10 -0
  82. package/dist/{lib/Helper/PackageManager.js → src/utils/package-manager.js} +42 -74
  83. package/dist/src/utils/package-manager.js.map +1 -0
  84. package/dist/src/utils/release-registry.d.ts +1 -0
  85. package/dist/src/utils/release-registry.js +68 -0
  86. package/dist/src/utils/release-registry.js.map +1 -0
  87. package/dist/src/utils/sentrycli-utils.d.ts +4 -0
  88. package/dist/src/utils/sentrycli-utils.js +41 -0
  89. package/dist/src/utils/sentrycli-utils.js.map +1 -0
  90. package/dist/test/android/code-tools.test.d.ts +1 -0
  91. package/dist/test/android/code-tools.test.js +34 -0
  92. package/dist/test/android/code-tools.test.js.map +1 -0
  93. package/dist/test/sourcemaps/tools/vite.test.d.ts +1 -0
  94. package/dist/test/sourcemaps/tools/vite.test.js +132 -0
  95. package/dist/test/sourcemaps/tools/vite.test.js.map +1 -0
  96. package/dist/test/sourcemaps/tools/webpack.test.d.ts +1 -0
  97. package/dist/test/sourcemaps/tools/webpack.test.js +179 -0
  98. package/dist/test/sourcemaps/tools/webpack.test.js.map +1 -0
  99. package/dist/test/utils/ast-utils.test.js +42 -7
  100. package/dist/test/utils/ast-utils.test.js.map +1 -1
  101. package/dist/test/utils/clack-utils.test.d.ts +1 -0
  102. package/dist/test/utils/clack-utils.test.js +200 -0
  103. package/dist/test/utils/clack-utils.test.js.map +1 -0
  104. package/lib/Constants.ts +5 -0
  105. package/lib/Steps/ChooseIntegration.ts +7 -3
  106. package/lib/Steps/Integrations/Android.ts +23 -0
  107. package/lib/Steps/Integrations/ReactNative.ts +9 -3
  108. package/lib/Steps/PromptForParameters.ts +48 -3
  109. package/lib/Steps/SentryProjectSelector.ts +3 -1
  110. package/package.json +4 -3
  111. package/src/android/android-wizard.ts +204 -0
  112. package/src/android/code-tools.ts +170 -0
  113. package/src/android/gradle.ts +250 -0
  114. package/src/android/manifest.ts +180 -0
  115. package/src/android/templates.ts +88 -0
  116. package/src/apple/apple-wizard.ts +113 -35
  117. package/src/apple/cocoapod.ts +6 -3
  118. package/src/apple/code-tools.ts +46 -18
  119. package/src/apple/fastlane.ts +6 -12
  120. package/src/apple/templates.ts +2 -8
  121. package/src/apple/xcode-manager.ts +167 -25
  122. package/src/nextjs/nextjs-wizard.ts +72 -8
  123. package/src/nextjs/templates.ts +16 -2
  124. package/src/remix/remix-wizard.ts +10 -15
  125. package/src/sourcemaps/sourcemaps-wizard.ts +19 -5
  126. package/src/sourcemaps/tools/nextjs.ts +2 -2
  127. package/src/sourcemaps/tools/sentry-cli.ts +8 -7
  128. package/src/sourcemaps/tools/vite.ts +143 -79
  129. package/src/sourcemaps/tools/webpack.ts +369 -30
  130. package/src/sourcemaps/utils/detect-tool.ts +2 -1
  131. package/src/sveltekit/sdk-setup.ts +10 -6
  132. package/src/sveltekit/sveltekit-wizard.ts +5 -14
  133. package/src/telemetry.ts +2 -0
  134. package/src/utils/ast-utils.ts +29 -11
  135. package/src/utils/clack-utils.ts +485 -283
  136. package/src/utils/package-manager.ts +61 -0
  137. package/src/utils/release-registry.ts +19 -0
  138. package/src/utils/sentrycli-utils.ts +22 -0
  139. package/test/android/code-tools.test.ts +49 -0
  140. package/test/sourcemaps/tools/vite.test.ts +149 -0
  141. package/test/sourcemaps/tools/webpack.test.ts +303 -0
  142. package/test/utils/ast-utils.test.ts +28 -9
  143. package/test/utils/clack-utils.test.ts +142 -0
  144. package/dist/lib/Helper/PackageManager.d.ts +0 -22
  145. package/dist/lib/Helper/PackageManager.js.map +0 -1
  146. package/dist/src/utils/vendor/clack-custom-select.d.ts +0 -21
  147. package/dist/src/utils/vendor/clack-custom-select.js +0 -137
  148. package/dist/src/utils/vendor/clack-custom-select.js.map +0 -1
  149. package/lib/Helper/PackageManager.ts +0 -59
  150. package/src/utils/vendor/clack-custom-select.ts +0 -160
@@ -1,18 +1,25 @@
1
1
  // @ts-ignore - clack is ESM and TS complains about that. It works though
2
- import clack, { select } from '@clack/prompts';
2
+ import * as clack from '@clack/prompts';
3
3
  // @ts-ignore - magicast is ESM and TS complains about that. It works though
4
4
  import { generateCode, parseModule } from 'magicast';
5
5
  // @ts-ignore - magicast is ESM and TS complains about that. It works though
6
6
  import { addVitePlugin } from 'magicast/helpers';
7
7
 
8
+ import type { namedTypes as t } from 'ast-types';
9
+
10
+ import * as recast from 'recast';
11
+
8
12
  import * as Sentry from '@sentry/node';
9
13
 
10
14
  import chalk from 'chalk';
11
15
  import {
12
16
  abortIfCancelled,
13
17
  addDotEnvSentryBuildPluginFile,
18
+ askForToolConfigPath,
19
+ createNewConfigFile,
14
20
  getPackageDotJson,
15
21
  installPackage,
22
+ showCopyPasteInstructions,
16
23
  } from '../../utils/clack-utils';
17
24
  import { hasPackageInstalled } from '../../utils/package-json';
18
25
 
@@ -20,7 +27,7 @@ import {
20
27
  SourceMapUploadToolConfigurationFunction,
21
28
  SourceMapUploadToolConfigurationOptions,
22
29
  } from './types';
23
- import { findScriptFile, hasSentryContent } from '../../utils/ast-utils';
30
+ import { findFile, hasSentryContent } from '../../utils/ast-utils';
24
31
 
25
32
  import * as path from 'path';
26
33
  import * as fs from 'fs';
@@ -87,59 +94,44 @@ export const configureVitePlugin: SourceMapUploadToolConfigurationFunction =
87
94
  });
88
95
 
89
96
  const viteConfigPath =
90
- findScriptFile(path.resolve(process.cwd(), 'vite.config')) ||
91
- (await askForViteConfigPath());
97
+ findFile(path.resolve(process.cwd(), 'vite.config')) ??
98
+ (await askForToolConfigPath('Vite', 'vite.config.js'));
92
99
 
93
100
  let successfullyAdded = false;
94
101
  if (viteConfigPath) {
95
102
  successfullyAdded = await addVitePluginToConfig(viteConfigPath, options);
96
103
  } else {
97
- successfullyAdded = await createNewViteConfig(options);
104
+ successfullyAdded = await createNewConfigFile(
105
+ path.join(process.cwd(), 'vite.config.js'),
106
+ getViteConfigSnippet(options, false),
107
+ 'More information about vite configs: https://vitejs.dev/config/',
108
+ );
109
+ Sentry.setTag(
110
+ 'created-new-config',
111
+ successfullyAdded ? 'success' : 'fail',
112
+ );
98
113
  }
99
114
 
100
115
  if (successfullyAdded) {
116
+ clack.log.info(
117
+ `We recommend checking the ${
118
+ viteConfigPath ? 'modified' : 'added'
119
+ } file after the wizard finished to ensure it works with your build setup.`,
120
+ );
121
+
101
122
  Sentry.setTag('ast-mod', 'success');
102
123
  } else {
103
124
  Sentry.setTag('ast-mod', 'fail');
104
125
  await showCopyPasteInstructions(
105
126
  path.basename(viteConfigPath || 'vite.config.js'),
106
- options,
127
+ getViteConfigSnippet(options, true),
107
128
  );
108
129
  }
109
130
 
110
131
  await addDotEnvSentryBuildPluginFile(options.authToken);
111
132
  };
112
133
 
113
- async function createNewViteConfig(
114
- options: SourceMapUploadToolConfigurationOptions,
115
- ): Promise<boolean> {
116
- try {
117
- await fs.promises.writeFile(
118
- 'vite.config.js',
119
- getViteConfigSnippet(options, false),
120
- );
121
- Sentry.setTag('created-new-config', 'success');
122
- return true;
123
- } catch (e) {
124
- debug(e);
125
- Sentry.setTag('created-new-config', 'fail');
126
- clack.log.warn(
127
- `Could not create a new ${chalk.cyan(
128
- 'vite.config.js',
129
- )} file. Please create one manually and follow the instructions below.`,
130
- );
131
-
132
- clack.log.info(
133
- chalk.gray(
134
- 'More information about vite configs: https://vitejs.dev/config/',
135
- ),
136
- );
137
-
138
- return false;
139
- }
140
- }
141
-
142
- async function addVitePluginToConfig(
134
+ export async function addVitePluginToConfig(
143
135
  viteConfigPath: string,
144
136
  options: SourceMapUploadToolConfigurationOptions,
145
137
  ): Promise<boolean> {
@@ -152,7 +144,7 @@ async function addVitePluginToConfig(
152
144
 
153
145
  const mod = parseModule(viteConfigContent);
154
146
 
155
- if (hasSentryContent(mod)) {
147
+ if (hasSentryContent(mod.$ast as t.Program)) {
156
148
  const shouldContinue = await abortIfCancelled(
157
149
  clack.select({
158
150
  message: `${prettyViteConfigFilename} already contains Sentry-related code. Should the wizard modify it anyway?`,
@@ -176,6 +168,12 @@ async function addVitePluginToConfig(
176
168
  }
177
169
  }
178
170
 
171
+ const enabledSourcemaps = enableSourcemapGeneration(mod.$ast as t.Program);
172
+ if (!enabledSourcemaps) {
173
+ Sentry.setTag('ast-mod-fail-reason', 'insertion-fail');
174
+ return false;
175
+ }
176
+
179
177
  const { orgSlug: org, projectSlug: project, selfHosted, url } = options;
180
178
 
181
179
  addVitePlugin(mod, {
@@ -194,7 +192,7 @@ async function addVitePluginToConfig(
194
192
  await fs.promises.writeFile(viteConfigPath, code);
195
193
 
196
194
  clack.log.success(
197
- `Added the Sentry Vite plugin to ${prettyViteConfigFilename}`,
195
+ `Added the Sentry Vite plugin to ${prettyViteConfigFilename} and enabled source maps`,
198
196
  );
199
197
 
200
198
  return true;
@@ -205,56 +203,122 @@ async function addVitePluginToConfig(
205
203
  }
206
204
  }
207
205
 
208
- async function showCopyPasteInstructions(
209
- viteConfigFilename: string,
210
- options: SourceMapUploadToolConfigurationOptions,
211
- ) {
212
- clack.log.step(
213
- `Add the following code to your ${chalk.cyan(viteConfigFilename)} file:`,
214
- );
206
+ function enableSourcemapGeneration(program: t.Program): boolean {
207
+ const configObj = getViteConfigObject(program);
208
+
209
+ if (!configObj) {
210
+ return false;
211
+ }
215
212
 
216
- // Intentionally logging directly to console here so that the code can be copied/pasted directly
217
- // eslint-disable-next-line no-console
218
- console.log(`\n${getViteConfigSnippet(options, true)}`);
213
+ const b = recast.types.builders;
219
214
 
220
- await abortIfCancelled(
221
- select({
222
- message: 'Did you copy the snippet above?',
223
- options: [{ label: 'Yes, continue!', value: true }],
224
- initialValue: true,
225
- }),
215
+ const buildProp = configObj.properties.find(
216
+ (p: t.ObjectProperty) =>
217
+ p.key.type === 'Identifier' && p.key.name === 'build',
226
218
  );
219
+
220
+ // case 1: build property doesn't exist yet, so we can just add it
221
+ if (!buildProp) {
222
+ configObj.properties.push(
223
+ b.objectProperty(
224
+ b.identifier('build'),
225
+ b.objectExpression([
226
+ b.objectProperty(b.identifier('sourcemap'), b.booleanLiteral(true)),
227
+ ]),
228
+ ),
229
+ );
230
+ return true;
231
+ }
232
+
233
+ const isValidBuildProp =
234
+ buildProp.type === 'ObjectProperty' &&
235
+ buildProp.value.type === 'ObjectExpression';
236
+
237
+ if (!isValidBuildProp) {
238
+ return false;
239
+ }
240
+
241
+ const sourceMapsProp =
242
+ buildProp.value.type === 'ObjectExpression' &&
243
+ buildProp.value.properties.find(
244
+ (p: t.ObjectProperty) =>
245
+ p.key.type === 'Identifier' && p.key.name === 'sourcemap',
246
+ );
247
+
248
+ // case 2: build.sourcemap property doesn't exist yet, so we just add it
249
+ if (!sourceMapsProp && buildProp.value.type === 'ObjectExpression') {
250
+ buildProp.value.properties.push(
251
+ b.objectProperty(b.identifier('sourcemap'), b.booleanLiteral(true)),
252
+ );
253
+ return true;
254
+ }
255
+
256
+ if (!sourceMapsProp || sourceMapsProp.type !== 'ObjectProperty') {
257
+ return false;
258
+ }
259
+
260
+ // case 3: build.sourcemap property exists, and it's set to 'hidden'
261
+ if (
262
+ sourceMapsProp.value.type === 'StringLiteral' &&
263
+ sourceMapsProp.value.value === 'hidden'
264
+ ) {
265
+ // nothing to do for us
266
+ return true;
267
+ }
268
+
269
+ // case 4: build.sourcemap property exists, but it's not enabled, so we set it to true
270
+ // or it is already true in which case this is a noop
271
+ sourceMapsProp.value = b.booleanLiteral(true);
272
+ return true;
227
273
  }
228
274
 
229
- async function askForViteConfigPath(): Promise<string | undefined> {
230
- const hasViteConfig = await abortIfCancelled(
231
- clack.confirm({
232
- message: `Do you have a vite config file (e.g. ${chalk.cyan(
233
- 'vite.config.js',
234
- )}?`,
235
- initialValue: true,
236
- }),
237
- );
275
+ function getViteConfigObject(
276
+ program: t.Program,
277
+ ): t.ObjectExpression | undefined {
278
+ const defaultExport = program.body.find(
279
+ (s) => s.type === 'ExportDefaultDeclaration',
280
+ ) as t.ExportDefaultDeclaration;
238
281
 
239
- if (!hasViteConfig) {
282
+ if (!defaultExport) {
240
283
  return undefined;
241
284
  }
242
285
 
243
- return await abortIfCancelled(
244
- clack.text({
245
- message: 'Please enter the path to your vite config file:',
246
- placeholder: `.${path.sep}vite.config.js`,
247
- validate: (value) => {
248
- if (!value) {
249
- return 'Please enter a path.';
250
- }
286
+ if (defaultExport.declaration.type === 'ObjectExpression') {
287
+ return defaultExport.declaration;
288
+ }
289
+
290
+ if (
291
+ defaultExport.declaration.type === 'CallExpression' &&
292
+ defaultExport.declaration.arguments[0].type === 'ObjectExpression'
293
+ ) {
294
+ return defaultExport.declaration.arguments[0];
295
+ }
296
+
297
+ if (defaultExport.declaration.type === 'Identifier') {
298
+ const configId = defaultExport.declaration.name;
299
+ return findConfigNode(configId, program);
300
+ }
301
+
302
+ return undefined;
303
+ }
251
304
 
252
- try {
253
- fs.accessSync(value);
254
- } catch {
255
- return 'Could not access the file at this path.';
305
+ function findConfigNode(
306
+ configId: string,
307
+ program: t.Program,
308
+ ): t.ObjectExpression | undefined {
309
+ for (const node of program.body) {
310
+ if (node.type === 'VariableDeclaration') {
311
+ for (const declaration of node.declarations) {
312
+ if (
313
+ declaration.type === 'VariableDeclarator' &&
314
+ declaration.id.type === 'Identifier' &&
315
+ declaration.id.name === configId &&
316
+ declaration.init?.type === 'ObjectExpression'
317
+ ) {
318
+ return declaration.init;
256
319
  }
257
- },
258
- }),
259
- );
320
+ }
321
+ }
322
+ }
323
+ return undefined;
260
324
  }