@sentry/wizard 3.15.0 → 3.16.1

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 (98) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/lib/Steps/ChooseIntegration.js +1 -1
  3. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  4. package/dist/lib/Steps/Integrations/Cordova.js +7 -0
  5. package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
  6. package/dist/lib/Steps/Integrations/ReactNative.d.ts +7 -32
  7. package/dist/lib/Steps/Integrations/ReactNative.js +17 -485
  8. package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
  9. package/dist/package.json +1 -1
  10. package/dist/src/android/android-wizard.js +13 -18
  11. package/dist/src/android/android-wizard.js.map +1 -1
  12. package/dist/src/apple/apple-wizard.js +11 -4
  13. package/dist/src/apple/apple-wizard.js.map +1 -1
  14. package/dist/src/apple/cocoapod.d.ts +1 -0
  15. package/dist/src/apple/cocoapod.js +36 -13
  16. package/dist/src/apple/cocoapod.js.map +1 -1
  17. package/dist/src/nextjs/nextjs-wizard.js +1 -1
  18. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  19. package/dist/src/react-native/glob.d.ts +3 -0
  20. package/dist/src/react-native/glob.js +18 -0
  21. package/dist/src/react-native/glob.js.map +1 -0
  22. package/dist/src/react-native/gradle.d.ts +4 -0
  23. package/dist/src/react-native/gradle.js +49 -0
  24. package/dist/src/react-native/gradle.js.map +1 -0
  25. package/dist/src/react-native/javascript.d.ts +8 -0
  26. package/dist/src/react-native/javascript.js +25 -0
  27. package/dist/src/react-native/javascript.js.map +1 -0
  28. package/dist/src/react-native/options.d.ts +4 -0
  29. package/dist/src/react-native/options.js +3 -0
  30. package/dist/src/react-native/options.js.map +1 -0
  31. package/dist/src/react-native/react-native-wizard.d.ts +9 -0
  32. package/dist/src/react-native/react-native-wizard.js +356 -0
  33. package/dist/src/react-native/react-native-wizard.js.map +1 -0
  34. package/dist/src/react-native/uninstall.d.ts +2 -0
  35. package/dist/src/react-native/uninstall.js +130 -0
  36. package/dist/src/react-native/uninstall.js.map +1 -0
  37. package/dist/src/react-native/xcode.d.ts +18 -0
  38. package/dist/src/react-native/xcode.js +170 -0
  39. package/dist/src/react-native/xcode.js.map +1 -0
  40. package/dist/src/remix/remix-wizard.js +1 -1
  41. package/dist/src/remix/remix-wizard.js.map +1 -1
  42. package/dist/src/sourcemaps/tools/nextjs.js +3 -3
  43. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
  44. package/dist/src/sourcemaps/tools/sentry-cli.js +1 -1
  45. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  46. package/dist/src/sveltekit/sveltekit-wizard.js +1 -1
  47. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  48. package/dist/src/utils/clack-utils.d.ts +19 -3
  49. package/dist/src/utils/clack-utils.js +141 -39
  50. package/dist/src/utils/clack-utils.js.map +1 -1
  51. package/dist/src/utils/semver.d.ts +5 -0
  52. package/dist/src/utils/semver.js +27 -0
  53. package/dist/src/utils/semver.js.map +1 -0
  54. package/dist/src/utils/sentrycli-utils.js +4 -1
  55. package/dist/src/utils/sentrycli-utils.js.map +1 -1
  56. package/dist/src/utils/types.d.ts +3 -0
  57. package/dist/src/utils/types.js.map +1 -1
  58. package/dist/test/react-native/gradle.test.js +57 -0
  59. package/dist/test/react-native/gradle.test.js.map +1 -0
  60. package/dist/test/react-native/javascript.test.js +47 -0
  61. package/dist/test/react-native/javascript.test.js.map +1 -0
  62. package/dist/test/react-native/xcode.test.d.ts +1 -0
  63. package/dist/test/react-native/xcode.test.js +144 -0
  64. package/dist/test/react-native/xcode.test.js.map +1 -0
  65. package/lib/Steps/ChooseIntegration.ts +1 -1
  66. package/lib/Steps/Integrations/Cordova.ts +7 -0
  67. package/lib/Steps/Integrations/ReactNative.ts +17 -573
  68. package/package.json +1 -1
  69. package/src/android/android-wizard.ts +3 -18
  70. package/src/apple/apple-wizard.ts +12 -3
  71. package/src/apple/cocoapod.ts +20 -9
  72. package/src/nextjs/nextjs-wizard.ts +1 -1
  73. package/src/react-native/glob.ts +13 -0
  74. package/src/react-native/gradle.ts +26 -0
  75. package/src/react-native/javascript.ts +33 -0
  76. package/src/react-native/options.ts +5 -0
  77. package/src/react-native/react-native-wizard.ts +369 -0
  78. package/src/react-native/uninstall.ts +107 -0
  79. package/src/react-native/xcode.ts +228 -0
  80. package/src/remix/remix-wizard.ts +2 -2
  81. package/src/sourcemaps/tools/nextjs.ts +6 -6
  82. package/src/sourcemaps/tools/sentry-cli.ts +1 -1
  83. package/src/sveltekit/sveltekit-wizard.ts +1 -1
  84. package/src/utils/clack-utils.ts +229 -74
  85. package/src/utils/semver.ts +33 -0
  86. package/src/utils/sentrycli-utils.ts +3 -1
  87. package/src/utils/types.ts +3 -0
  88. package/test/react-native/gradle.test.ts +310 -0
  89. package/test/react-native/javascript.test.ts +131 -0
  90. package/test/react-native/xcode.test.ts +238 -0
  91. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js +0 -198
  92. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js.map +0 -1
  93. package/dist/lib/__tests__/Setup.js +0 -57
  94. package/dist/lib/__tests__/Setup.js.map +0 -1
  95. package/lib/Steps/Integrations/__tests__/ReactNative.ts +0 -136
  96. package/lib/__tests__/Setup.ts +0 -42
  97. /package/dist/{lib/Steps/Integrations/__tests__/ReactNative.d.ts → test/react-native/gradle.test.d.ts} +0 -0
  98. /package/dist/{lib/__tests__/Setup.d.ts → test/react-native/javascript.test.d.ts} +0 -0
@@ -1,584 +1,28 @@
1
- /* eslint-disable max-lines */
2
- import { exec } from 'child_process';
3
- import * as fs from 'fs';
4
- import type { Answers } from 'inquirer';
5
- import { prompt } from 'inquirer';
6
- import * as _ from 'lodash';
7
- import * as path from 'path';
8
- import { promisify } from 'util';
9
-
10
- import type { Args } from '../../Constants';
11
- import {
12
- exists,
13
- matchesContent,
14
- matchFiles,
15
- patchMatchingFile,
16
- } from '../../Helper/File';
17
- import { dim, green, l, nl, red } from '../../Helper/Logging';
18
- import { checkPackageVersion } from '../../Helper/Package';
19
- import {
20
- detectPackageManger,
21
- installPackageWithPackageManager,
22
- } from '../../../src/utils/package-manager';
23
- import { SentryCli } from '../../Helper/SentryCli';
24
- import { MobileProject } from './MobileProject';
25
- import { BottomBar } from '../../Helper/BottomBar';
26
- import { URL } from 'url';
27
-
28
- const xcode = require('xcode');
29
-
30
- export const COMPATIBLE_REACT_NATIVE_VERSIONS = '>=0.69.0';
31
- export const COMPATIBLE_SDK_VERSION = '>= 5.0.0';
32
-
33
- export const SENTRY_REACT_NATIVE_PACKAGE = '@sentry/react-native';
34
- export const REACT_NATIVE_PACKAGE = 'react-native';
35
-
36
- export const DOCS_MANUAL_STEPS =
37
- 'https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/';
38
-
39
- export class ReactNative extends MobileProject {
40
- /**
41
- * All React Native versions have app/build.gradle with android section.
42
- */
43
- private static _buildGradleAndroidSectionBeginning = /^android {/m;
44
-
45
- private url: string | undefined;
46
-
47
- protected _answers: Answers;
48
- protected _sentryCli: SentryCli;
1
+ import { Answers } from 'inquirer';
2
+ import { type Args } from '../../Constants';
3
+ import { BaseIntegration } from './BaseIntegration';
4
+ import { runReactNativeWizard } from '../../../src/react-native/react-native-wizard';
49
5
 
6
+ export class ReactNative extends BaseIntegration {
7
+ argv: Args;
50
8
  public constructor(protected _argv: Args) {
51
9
  super(_argv);
52
- this.url = _argv.url;
53
- this._sentryCli = new SentryCli(this._argv);
10
+ this.argv = _argv;
54
11
  }
55
12
 
56
- public async emit(answers: Answers): Promise<Answers> {
57
- if (this._argv.uninstall) {
58
- return this.uninstall(answers);
59
- }
60
- if (!(await this.shouldEmit(answers))) {
61
- return {};
62
- }
63
- nl();
64
-
65
- let userAnswers: Answers = { continue: true };
66
- const packageManager = detectPackageManger();
67
-
68
- const hasCompatibleReactNativeVersion = checkPackageVersion(
69
- this._readAppPackage(),
70
- REACT_NATIVE_PACKAGE,
71
- COMPATIBLE_REACT_NATIVE_VERSIONS,
72
- true,
73
- );
74
- if (!hasCompatibleReactNativeVersion && !this._argv.quiet) {
75
- userAnswers = await prompt({
76
- message:
77
- "Your version of React Native is not compatible with Sentry's React Native SDK. Do you want to continue?",
78
- name: 'continue',
79
- default: false,
80
- type: 'confirm',
81
- });
82
- nl();
83
- }
84
- if (!userAnswers.continue) {
85
- throw new Error(
86
- `Please upgrade to a version that is compatible with ${COMPATIBLE_REACT_NATIVE_VERSIONS}. Or use ${DOCS_MANUAL_STEPS}`,
87
- );
88
- }
89
-
90
- if (packageManager) {
91
- BottomBar.show(`Adding ${SENTRY_REACT_NATIVE_PACKAGE}...`);
92
- await installPackageWithPackageManager(
93
- packageManager,
94
- SENTRY_REACT_NATIVE_PACKAGE,
95
- );
96
- BottomBar.hide();
97
- green(`✓ Added \`${SENTRY_REACT_NATIVE_PACKAGE}\``);
98
- }
99
- const hasCompatibleSentryReactNativeVersion = checkPackageVersion(
100
- this._readAppPackage(),
101
- SENTRY_REACT_NATIVE_PACKAGE,
102
- COMPATIBLE_SDK_VERSION,
103
- true,
104
- );
105
- if (!hasCompatibleSentryReactNativeVersion && !this._argv.quiet) {
106
- userAnswers = await prompt({
107
- message: `Your version of ${SENTRY_REACT_NATIVE_PACKAGE} is not compatible with this wizard. Do you want to continue?`,
108
- name: 'continue',
109
- default: false,
110
- type: 'confirm',
111
- });
112
- nl();
113
- }
114
- if (!userAnswers.continue) {
115
- throw new Error(
116
- `Please upgrade to a version that is compatible with ${COMPATIBLE_SDK_VERSION}.`,
117
- );
118
- }
119
-
120
- const sentryCliProperties =
121
- this._sentryCli.convertAnswersToProperties(answers);
122
-
123
- const promises = this.getPlatforms(answers).map(
124
- async (platform: string) => {
125
- try {
126
- if (platform === 'ios') {
127
- await patchMatchingFile(
128
- 'ios/*.xcodeproj/project.pbxproj',
129
- this._patchXcodeProj.bind(this),
130
- );
131
- green('✓ Patched build script in Xcode project.');
132
- BottomBar.show('Adding Sentry pods...');
133
- await this._podInstall();
134
- BottomBar.hide();
135
- green('✓ Pods installed.');
136
- } else {
137
- await patchMatchingFile(
138
- '**/app/build.gradle',
139
- this._patchBuildGradle.bind(this),
140
- );
141
- green('✓ Patched build.gradle file.');
142
- }
143
- await this._patchJsSentryInit(platform, answers);
144
- await this._addSentryProperties(platform, sentryCliProperties);
145
- green(`✓ Added sentry.properties file to ${platform}`);
146
- } catch (e) {
147
- red(e);
148
- }
149
- },
150
- );
151
-
152
- await Promise.all(promises);
153
-
154
- let host: string | null = null;
155
- try {
156
- host = new URL(this.url || '').host;
157
- } catch (_error) {
158
- // ignore
159
- }
160
- const orgSlug = _.get(answers, 'config.organization.slug', null);
161
- const projectId = _.get(answers, 'config.project.id', null);
162
- const projectIssuesUrl =
163
- host && orgSlug && projectId
164
- ? `https://${orgSlug}.${host}/issues/?project=${projectId}`
165
- : null;
166
-
167
- l(`
168
- To make sure everything is set up correctly, put the following code snippet into your application.
169
- The snippet will create a button that, when tapped, sends a test event to Sentry.
170
- `);
171
-
172
- if (projectIssuesUrl) {
173
- l(`After that check your project issues:`);
174
- l(projectIssuesUrl);
175
- nl();
176
- }
177
-
178
- l(
179
- `<Button title='Try!' onPress={ () => { Sentry.captureException(new Error('First error')) }}/>`,
180
- );
181
- nl();
182
-
183
- if (!this._argv.quiet) {
184
- await prompt({
185
- message: 'Have you successfully sent a test event?',
186
- name: 'snippet',
187
- default: true,
188
- type: 'confirm',
189
- });
190
- }
13
+ public async emit(_answers: Answers): Promise<Answers> {
14
+ await runReactNativeWizard({
15
+ promoCode: this._argv.promoCode,
16
+ url: this._argv.url,
17
+ telemetryEnabled: !this._argv.disableTelemetry,
18
+ uninstall: this._argv.uninstall,
19
+ // eslint-disable-next-line no-console
20
+ }).catch(console.error);
191
21
 
192
- return answers;
193
- }
194
-
195
- public async uninstall(_answers: Answers): Promise<Answers> {
196
- await patchMatchingFile(
197
- '**/*.xcodeproj/project.pbxproj',
198
- this._unpatchXcodeProj.bind(this),
199
- );
200
- await patchMatchingFile(
201
- '**/app/build.gradle',
202
- this._unpatchBuildGradle.bind(this),
203
- );
204
22
  return {};
205
23
  }
206
24
 
207
- // eslint-disable-next-line @typescript-eslint/require-await
208
- protected async _shouldConfigurePlatform(platform: string): Promise<boolean> {
209
- let result = false;
210
-
211
- if (!exists(`${platform}/sentry.properties`)) {
212
- result = true;
213
- this.debug(`${platform}/sentry.properties not exists`);
214
- }
215
-
216
- if (!matchesContent('**/*.xcodeproj/project.pbxproj', /sentry-cli/gi)) {
217
- result = true;
218
- this.debug('**/*.xcodeproj/project.pbxproj not matched');
219
- }
220
-
221
- if (!matchesContent('**/app/build.gradle', /sentry\.gradle/gi)) {
222
- result = true;
223
- this.debug('**/app/build.gradle not matched');
224
- }
225
-
226
- const regex = /Sentry/gi;
227
- if (
228
- exists(`index.${platform}.js`) &&
229
- !matchesContent(`index.${platform}.js`, regex)
230
- ) {
231
- result = true;
232
- this.debug(`index.${platform}.js not matched`);
233
- }
234
- if (exists('App.js') && !matchesContent('App.js', regex)) {
235
- result = true;
236
- this.debug('index.js or App.js not matched');
237
- }
238
-
239
- if (this._argv.uninstall) {
240
- // if we uninstall we need to invert the result so we remove already patched
241
- // but leave untouched platforms as they are
242
- return !result;
243
- }
244
-
245
- return result;
246
- }
247
-
248
- private _readAppPackage(): Record<string, unknown> {
249
- let appPackage: Record<string, unknown> = {};
250
-
251
- try {
252
- appPackage = JSON.parse(
253
- fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'),
254
- );
255
- } catch {
256
- // We don't need to have this
257
- }
258
-
259
- return appPackage;
260
- }
261
-
262
- private async _podInstall(): Promise<void> {
263
- await promisify(exec)('npx --yes pod-install --non-interactive --quiet');
264
- }
265
-
266
- private async _patchJsSentryInit(
267
- platform: string,
268
- answers: Answers,
269
- ): Promise<void> {
270
- const prefixGlob = '{.,./src}';
271
- const suffixGlob = '@(j|t|cj|mj)s?(x)';
272
- const platformGlob = `index.${platform}.${suffixGlob}`;
273
- // rm 0.49 introduced an App.js for both platforms
274
- const universalGlob = `App.${suffixGlob}`;
275
- const jsFileGlob = `${prefixGlob}/+(${platformGlob}|${universalGlob})`;
276
-
277
- const jsFileToPatch = matchFiles(jsFileGlob);
278
- if (jsFileToPatch.length !== 0) {
279
- await patchMatchingFile(
280
- jsFileGlob,
281
- this._patchJs.bind(this),
282
- answers,
283
- platform,
284
- );
285
- green(`✓ Patched ${jsFileToPatch.join(', ')} file(s).`);
286
- } else {
287
- red(`✗ Could not find ${platformGlob} nor ${universalGlob} files.`);
288
- red('✗ Please, visit https://docs.sentry.io/platforms/react-native');
289
- }
290
- }
291
-
292
- private _addSentryProperties(
293
- platform: string,
294
- properties: any,
295
- ): Promise<void> {
296
- let rv = Promise.resolve();
297
-
298
- // This will create the ios/android folder before trying to write
299
- // sentry.properties in it which would fail otherwise
300
- if (!fs.existsSync(platform)) {
301
- dim(`${platform} folder did not exist, creating it.`);
302
- fs.mkdirSync(platform);
303
- }
304
- const fn = path.join(platform, 'sentry.properties');
305
-
306
- if (platform === 'android' && properties['cli/executable']) {
307
- // We don't need to write the sentry-cli path in the properties file
308
- // since our gradle plugins already pick it up on the correct spot
309
- delete properties['cli/executable'];
310
- }
311
- rv = rv.then(() =>
312
- fs.writeFileSync(fn, this._sentryCli.dumpProperties(properties)),
313
- );
314
-
315
- return rv;
316
- }
317
-
318
- private _patchJs(
319
- contents: string,
320
- _filename: string,
321
- answers: Answers,
322
- platform?: string,
323
- ): Promise<string | null> {
324
- // since the init call could live in other places too, we really only
325
- // want to do this if we managed to patch any of the other files as well.
326
- if (contents.match(/Sentry.config\(/)) {
327
- return Promise.resolve(null);
328
- }
329
-
330
- // if we match @sentry\/react-native somewhere, we already patched the file
331
- // and no longer need to
332
- if (contents.match('@sentry/react-native')) {
333
- return Promise.resolve(contents);
334
- }
335
-
336
- let dsn = '__DSN__';
337
- this.getPlatforms(answers).forEach((selectedPlatform: string) => {
338
- if (platform && selectedPlatform === platform) {
339
- dsn = _.get(answers, 'config.dsn.public', null);
340
- } else if (platform === undefined) {
341
- dsn = _.get(answers, 'config.dsn.public', null);
342
- }
343
- });
344
-
345
- return Promise.resolve(
346
- contents.replace(
347
- /^([^]*)(import\s+[^;]*?;$)/m,
348
- (match) =>
349
- // eslint-disable-next-line prefer-template
350
- match +
351
- "\n\nimport * as Sentry from '@sentry/react-native';\n\n" +
352
- 'Sentry.init({ \n' +
353
- ` dsn: '${dsn}', \n` +
354
- '});\n',
355
- ),
356
- );
357
- }
358
-
359
- // ANDROID -----------------------------------------
360
-
361
- private _patchBuildGradle(contents: string): Promise<string | null> {
362
- const applyFrom =
363
- 'apply from: "../../node_modules/@sentry/react-native/sentry.gradle"';
364
- if (contents.indexOf(applyFrom) >= 0) {
365
- return Promise.resolve(null);
366
- }
367
-
368
- return Promise.resolve(
369
- contents.replace(
370
- ReactNative._buildGradleAndroidSectionBeginning,
371
- // eslint-disable-next-line prefer-template
372
- (match) => applyFrom + '\n' + match,
373
- ),
374
- );
375
- }
376
-
377
- private _unpatchBuildGradle(contents: string): Promise<string> {
378
- return Promise.resolve(
379
- contents.replace(
380
- /^\s*apply from: ["']..\/..\/node_modules\/@sentry\/react-native\/sentry.gradle["'];?\s*?\r?\n/m,
381
- '',
382
- ),
383
- );
384
- }
385
-
386
- // IOS -----------------------------------------
387
-
388
- private _patchExistingXcodeBuildScripts(buildScripts: any): void {
389
- for (const script of buildScripts) {
390
- if (
391
- !script.shellScript.match(/\/scripts\/react-native-xcode\.sh/i) ||
392
- script.shellScript.match(/sentry-cli\s+react-native\s+xcode/i)
393
- ) {
394
- continue;
395
- }
396
- let code = JSON.parse(script.shellScript);
397
- code =
398
- // eslint-disable-next-line prefer-template, @typescript-eslint/restrict-plus-operands
399
- 'export SENTRY_PROPERTIES=sentry.properties\n' +
400
- 'export EXTRA_PACKAGER_ARGS="--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map"\n' +
401
- code.replace(
402
- '$REACT_NATIVE_XCODE',
403
- () =>
404
- // eslint-disable-next-line no-useless-escape
405
- '\\"../node_modules/@sentry/cli/bin/sentry-cli react-native xcode $REACT_NATIVE_XCODE\\"',
406
- ) +
407
- '\n/bin/sh -c "$WITH_ENVIRONMENT ../node_modules/@sentry/react-native/scripts/collect-modules.sh"\n';
408
- script.shellScript = JSON.stringify(code);
409
- }
410
- }
411
-
412
- private _addNewXcodeBuildPhaseForSymbols(buildScripts: any, proj: any): void {
413
- for (const script of buildScripts) {
414
- if (
415
- script.shellScript.match(
416
- /sentry-cli\s+(upload-dsym|debug-files upload)/,
417
- )
418
- ) {
419
- return;
420
- }
421
- }
422
-
423
- proj.addBuildPhase(
424
- [],
425
- 'PBXShellScriptBuildPhase',
426
- 'Upload Debug Symbols to Sentry',
427
- null,
428
- {
429
- shellPath: '/bin/sh',
430
- shellScript: `
431
- WITH_ENVIRONMENT="../node_modules/react-native/scripts/xcode/with-environment.sh"
432
- if [ -f "$WITH_ENVIRONMENT" ]; then
433
- . "$WITH_ENVIRONMENT"
434
- fi
435
- export SENTRY_PROPERTIES=sentry.properties
436
- [ "$SENTRY_INCLUDE_NATIVE_SOURCES" = "true" ] && INCLUDE_SOURCES_FLAG="--include-sources" || INCLUDE_SOURCES_FLAG=""
437
- ../node_modules/@sentry/cli/bin/sentry-cli debug-files upload "$INCLUDE_SOURCES_FLAG" "$DWARF_DSYM_FOLDER_PATH"
438
- `,
439
- },
440
- );
441
- }
442
-
443
- private _patchXcodeProj(
444
- contents: string,
445
- filename: string,
446
- ): Promise<string | undefined> {
447
- const proj = xcode.project(filename);
448
- return new Promise((resolve, reject) => {
449
- proj.parse((err: any) => {
450
- if (err) {
451
- reject(err);
452
- return;
453
- }
454
-
455
- const buildScripts = [];
456
- for (const key in proj.hash.project.objects.PBXShellScriptBuildPhase ||
457
- {}) {
458
- if (
459
- // eslint-disable-next-line no-prototype-builtins
460
- proj.hash.project.objects.PBXShellScriptBuildPhase.hasOwnProperty(
461
- key,
462
- )
463
- ) {
464
- const val = proj.hash.project.objects.PBXShellScriptBuildPhase[key];
465
- if (val.isa) {
466
- buildScripts.push(val);
467
- }
468
- }
469
- }
470
-
471
- try {
472
- this._patchExistingXcodeBuildScripts(buildScripts);
473
- } catch (e) {
474
- red(e);
475
- }
476
- try {
477
- this._addNewXcodeBuildPhaseForSymbols(buildScripts, proj);
478
- } catch (e) {
479
- red(e);
480
- }
481
-
482
- // we always modify the xcode file in memory but we only want to save it
483
- // in case the user wants configuration for ios. This is why we check
484
- // here first if changes are made before we might prompt the platform
485
- // continue prompt.
486
- const newContents = proj.writeSync();
487
- if (newContents === contents) {
488
- resolve(undefined);
489
- } else {
490
- resolve(newContents);
491
- }
492
- });
493
- });
494
- }
495
-
496
- private _unpatchXcodeBuildScripts(proj: any): void {
497
- const scripts = proj.hash.project.objects.PBXShellScriptBuildPhase || {};
498
- const firstTarget = proj.getFirstTarget().uuid;
499
- const nativeTargets = proj.hash.project.objects.PBXNativeTarget;
500
-
501
- // scripts to patch partially. Run this first so that we don't
502
- // accidentally delete some scripts later entirely that we only want to
503
- // rewrite.
504
- for (const key of Object.keys(scripts)) {
505
- const script = scripts[key];
506
-
507
- // ignore comments
508
- if (typeof script === 'string') {
509
- continue;
510
- }
511
-
512
- // ignore scripts that do not invoke the react-native-xcode command.
513
- if (!script.shellScript.match(/sentry-cli\s+react-native\s+xcode/i)) {
514
- continue;
515
- }
516
-
517
- script.shellScript = JSON.stringify(
518
- JSON.parse(script.shellScript)
519
- // remove sentry properties export
520
- .replace(/^export SENTRY_PROPERTIES=sentry.properties\r?\n/m, '')
521
- .replace(
522
- /^\/bin\/sh .*?..\/node_modules\/@sentry\/react-native\/scripts\/collect-modules.sh"?\r?\n/m,
523
- '',
524
- )
525
- // unwrap react-native-xcode.sh command. In case someone replaced it
526
- // entirely with the sentry-cli command we need to put the original
527
- // version back in.
528
- .replace(
529
- /\.\.\/node_modules\/@sentry\/cli\/bin\/sentry-cli\s+react-native\s+xcode\s+\$REACT_NATIVE_XCODE/i,
530
- '$REACT_NATIVE_XCODE',
531
- ),
532
- );
533
- }
534
-
535
- // scripts to kill entirely.
536
- for (const key of Object.keys(scripts)) {
537
- const script = scripts[key];
538
-
539
- // ignore comments and keys that got deleted
540
- if (typeof script === 'string' || script === undefined) {
541
- continue;
542
- }
543
-
544
- if (
545
- script.shellScript.match(
546
- /@sentry\/cli\/bin\/sentry-cli\s+(upload-dsym|debug-files upload)\b/,
547
- )
548
- ) {
549
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
550
- delete scripts[key];
551
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
552
- delete scripts[`${key}_comment`];
553
- const phases = nativeTargets[firstTarget].buildPhases;
554
- if (phases) {
555
- for (let i = 0; i < phases.length; i++) {
556
- if (phases[i].value === key) {
557
- phases.splice(i, 1);
558
- break;
559
- }
560
- }
561
- }
562
- continue;
563
- }
564
- }
565
- }
566
-
567
- private _unpatchXcodeProj(
568
- _contents: string,
569
- filename: string,
570
- ): Promise<string> {
571
- const proj = xcode.project(filename);
572
- return new Promise((resolve, reject) => {
573
- proj.parse((err: any) => {
574
- if (err) {
575
- reject(err);
576
- return;
577
- }
578
-
579
- this._unpatchXcodeBuildScripts(proj);
580
- resolve(proj.writeSync());
581
- });
582
- });
25
+ public async shouldConfigure(_answers: Answers): Promise<Answers> {
26
+ return this._shouldConfigure;
583
27
  }
584
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/wizard",
3
- "version": "3.15.0",
3
+ "version": "3.16.1",
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",
@@ -9,35 +9,20 @@ import * as manifest from './manifest';
9
9
  import * as codetools from './code-tools';
10
10
  import {
11
11
  CliSetupConfig,
12
- SENTRY_PROPERTIES_FILE,
13
12
  abort,
14
13
  addSentryCliConfig,
15
14
  confirmContinueIfNoOrDirtyGitRepo,
16
15
  getOrAskForProjectData,
17
16
  printWelcome,
17
+ propertiesCliSetupConfig,
18
18
  } from '../utils/clack-utils';
19
19
  import { WizardOptions } from '../utils/types';
20
20
  import { traceStep, withTelemetry } from '../telemetry';
21
21
  import chalk from 'chalk';
22
22
 
23
23
  const proguardMappingCliSetupConfig: CliSetupConfig = {
24
- filename: SENTRY_PROPERTIES_FILE,
24
+ ...propertiesCliSetupConfig,
25
25
  name: 'proguard mappings',
26
- likelyAlreadyHasAuthToken(contents: string): boolean {
27
- return !!contents.match(/auth\.token=./g);
28
- },
29
- tokenContent(authToken: string): string {
30
- return `auth.token=${authToken}`;
31
- },
32
- likelyAlreadyHasOrgAndProject(contents: string): boolean {
33
- return !!(
34
- contents.match(/defaults\.org=./g) &&
35
- contents.match(/defaults\.project=./g)
36
- );
37
- },
38
- orgAndProjContent(org: string, project: string): string {
39
- return `defaults.org=${org}\ndefaults.project=${project}`;
40
- },
41
26
  };
42
27
 
43
28
  export async function runAndroidWizard(options: WizardOptions): Promise<void> {
@@ -166,7 +151,7 @@ async function runAndroidWizardWithTelemetry(
166
151
  )} file.`,
167
152
  );
168
153
 
169
- await addSentryCliConfig(authToken, proguardMappingCliSetupConfig);
154
+ await addSentryCliConfig({ authToken }, proguardMappingCliSetupConfig);
170
155
 
171
156
  // ======== OUTRO ========
172
157
  const issuesPageLink = selfHosted