@sentry/wizard 3.7.1 → 3.9.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 (113) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/bin.ts +14 -0
  3. package/dist/bin.js +9 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/lib/Helper/Logging.d.ts +1 -0
  6. package/dist/lib/Helper/Logging.js +2 -1
  7. package/dist/lib/Helper/Logging.js.map +1 -1
  8. package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
  9. package/dist/lib/Setup.js +4 -0
  10. package/dist/lib/Setup.js.map +1 -1
  11. package/dist/lib/Steps/ChooseIntegration.js +12 -26
  12. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  13. package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
  14. package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
  15. package/dist/lib/Steps/Integrations/MobileProject.js.map +1 -1
  16. package/dist/lib/Steps/Integrations/ReactNative.js +5 -5
  17. package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
  18. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js +5 -6
  19. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js.map +1 -1
  20. package/dist/package.json +11 -7
  21. package/dist/src/apple/apple-wizard.js +31 -2
  22. package/dist/src/apple/apple-wizard.js.map +1 -1
  23. package/dist/src/apple/cocoapod.d.ts +2 -0
  24. package/dist/src/apple/cocoapod.js +122 -0
  25. package/dist/src/apple/cocoapod.js.map +1 -0
  26. package/dist/src/apple/code-tools.js +22 -12
  27. package/dist/src/apple/code-tools.js.map +1 -1
  28. package/dist/src/apple/fastlane.d.ts +2 -0
  29. package/dist/src/apple/fastlane.js +179 -0
  30. package/dist/src/apple/fastlane.js.map +1 -0
  31. package/dist/src/apple/templates.d.ts +1 -0
  32. package/dist/src/apple/templates.js +7 -3
  33. package/dist/src/apple/templates.js.map +1 -1
  34. package/dist/src/apple/xcode-manager.d.ts +1 -1
  35. package/dist/src/apple/xcode-manager.js +35 -28
  36. package/dist/src/apple/xcode-manager.js.map +1 -1
  37. package/dist/src/nextjs/nextjs-wizard.js +71 -81
  38. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  39. package/dist/src/sourcemaps/sourcemaps-wizard.js +61 -46
  40. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  41. package/dist/src/sourcemaps/tools/nextjs.d.ts +3 -0
  42. package/dist/src/sourcemaps/tools/nextjs.js +135 -0
  43. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -0
  44. package/dist/src/sourcemaps/tools/sentry-cli.js +120 -16
  45. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  46. package/dist/src/sourcemaps/tools/vite.js +102 -12
  47. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  48. package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
  49. package/dist/src/sourcemaps/utils/detect-tool.js +1 -0
  50. package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
  51. package/dist/src/sourcemaps/utils/other-wizards.js +35 -12
  52. package/dist/src/sourcemaps/utils/other-wizards.js.map +1 -1
  53. package/dist/src/sveltekit/sdk-setup.d.ts +9 -1
  54. package/dist/src/sveltekit/sdk-setup.js +73 -29
  55. package/dist/src/sveltekit/sdk-setup.js.map +1 -1
  56. package/dist/src/sveltekit/sveltekit-wizard.js +23 -13
  57. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  58. package/dist/src/utils/ast-utils.d.ts +8 -0
  59. package/dist/src/utils/ast-utils.js +45 -0
  60. package/dist/src/utils/ast-utils.js.map +1 -0
  61. package/dist/src/utils/bash.d.ts +2 -1
  62. package/dist/src/utils/bash.js +14 -2
  63. package/dist/src/utils/bash.js.map +1 -1
  64. package/dist/src/utils/clack-utils.d.ts +7 -14
  65. package/dist/src/utils/clack-utils.js +46 -2
  66. package/dist/src/utils/clack-utils.js.map +1 -1
  67. package/dist/src/utils/debug.d.ts +2 -0
  68. package/dist/src/utils/debug.js +51 -0
  69. package/dist/src/utils/debug.js.map +1 -0
  70. package/dist/src/utils/package-json.d.ts +1 -1
  71. package/dist/src/utils/package-json.js.map +1 -1
  72. package/dist/src/utils/types.d.ts +24 -0
  73. package/dist/src/utils/types.js.map +1 -1
  74. package/dist/test/utils/ast-utils.test.d.ts +1 -0
  75. package/dist/test/utils/ast-utils.test.js +21 -0
  76. package/dist/test/utils/ast-utils.test.js.map +1 -0
  77. package/lib/Helper/Logging.ts +1 -1
  78. package/lib/Helper/__tests__/MergeConfig.ts +9 -4
  79. package/lib/Setup.ts +5 -0
  80. package/lib/Steps/ChooseIntegration.ts +13 -3
  81. package/lib/Steps/Integrations/Cordova.ts +3 -3
  82. package/lib/Steps/Integrations/Electron.ts +1 -2
  83. package/lib/Steps/Integrations/MobileProject.ts +1 -1
  84. package/lib/Steps/Integrations/ReactNative.ts +23 -17
  85. package/lib/Steps/Integrations/__tests__/ReactNative.ts +24 -15
  86. package/package.json +11 -7
  87. package/src/apple/apple-wizard.ts +35 -3
  88. package/src/apple/cocoapod.ts +57 -0
  89. package/src/apple/code-tools.ts +80 -57
  90. package/src/apple/fastlane.ts +160 -0
  91. package/src/apple/templates.ts +26 -10
  92. package/src/apple/xcode-manager.ts +137 -120
  93. package/src/nextjs/nextjs-wizard.ts +4 -13
  94. package/src/sourcemaps/sourcemaps-wizard.ts +40 -28
  95. package/src/sourcemaps/tools/nextjs.ts +114 -0
  96. package/src/sourcemaps/tools/sentry-cli.ts +134 -8
  97. package/src/sourcemaps/tools/vite.ts +101 -12
  98. package/src/sourcemaps/utils/detect-tool.ts +3 -1
  99. package/src/sourcemaps/utils/other-wizards.ts +32 -13
  100. package/src/sveltekit/sdk-setup.ts +122 -43
  101. package/src/sveltekit/sveltekit-wizard.ts +15 -6
  102. package/src/utils/ast-utils.ts +20 -0
  103. package/src/utils/bash.ts +43 -30
  104. package/src/utils/clack-utils.ts +42 -14
  105. package/src/utils/debug.ts +20 -0
  106. package/src/utils/package-json.ts +1 -1
  107. package/src/utils/types.ts +22 -0
  108. package/test/utils/ast-utils.test.ts +44 -0
  109. package/dist/src/sveltekit/sentry-cli-setup.d.ts +0 -2
  110. package/dist/src/sveltekit/sentry-cli-setup.js +0 -71
  111. package/dist/src/sveltekit/sentry-cli-setup.js.map +0 -1
  112. package/package-lock.json +0 -8910
  113. package/src/sveltekit/sentry-cli-setup.ts +0 -27
@@ -3,79 +3,102 @@ import * as path from 'path';
3
3
  import * as templates from './templates';
4
4
  import * as Sentry from '@sentry/node';
5
5
 
6
- const swiftAppLaunchRegex = /(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|(init\s*\([^)]*\)\s*{)/im;
7
- const objcAppLaunchRegex = /-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(NSDictionary\s*\*\)\s*launchOptions\s*{/im;
6
+ const swiftAppLaunchRegex =
7
+ /(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|(init\s*\([^)]*\)\s*{)/im;
8
+ const objcAppLaunchRegex =
9
+ /-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(NSDictionary\s*\*\)\s*launchOptions\s*{/im;
8
10
  const swiftUIRegex = /struct[^:]+:\s*App\s*{/im;
9
11
 
10
12
  function isAppDelegateFile(filePath: string): boolean {
11
- const appLaunchRegex = filePath.toLowerCase().endsWith(".swift") ? swiftAppLaunchRegex : objcAppLaunchRegex;
13
+ const appLaunchRegex = filePath.toLowerCase().endsWith('.swift')
14
+ ? swiftAppLaunchRegex
15
+ : objcAppLaunchRegex;
12
16
 
13
- const fileContent = fs.readFileSync(filePath, 'utf8');
14
- return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
17
+ const fileContent = fs.readFileSync(filePath, 'utf8');
18
+ return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
15
19
  }
16
20
 
17
21
  function findAppDidFinishLaunchingWithOptions(dir: string): string | null {
18
- const files = fs.readdirSync(dir);
19
- //iterate over subdirectories later,
20
- //the appdelegate usually is in the top level
21
- const dirs: string[] = [];
22
+ const files = fs.readdirSync(dir);
23
+ //iterate over subdirectories later,
24
+ //the appdelegate usually is in the top level
25
+ const dirs: string[] = [];
22
26
 
23
- for (const file of files) {
24
- const filePath = path.join(dir, file);
25
- if (file.endsWith(".swift") || file.endsWith(".m") || file.endsWith(".mm")) {
26
- if (isAppDelegateFile(filePath)) {
27
- return filePath;
28
- }
29
- } else if (!file.startsWith(".") && !file.endsWith(".xcodeproj") && !file.endsWith(".xcassets") && fs.lstatSync(filePath).isDirectory()) {
30
- dirs.push(file);
31
- }
27
+ for (const file of files) {
28
+ const filePath = path.join(dir, file);
29
+ if (
30
+ file.endsWith('.swift') ||
31
+ file.endsWith('.m') ||
32
+ file.endsWith('.mm')
33
+ ) {
34
+ if (isAppDelegateFile(filePath)) {
35
+ return filePath;
36
+ }
37
+ } else if (
38
+ !file.startsWith('.') &&
39
+ !file.endsWith('.xcodeproj') &&
40
+ !file.endsWith('.xcassets') &&
41
+ fs.lstatSync(filePath).isDirectory()
42
+ ) {
43
+ dirs.push(file);
32
44
  }
45
+ }
33
46
 
34
- for (const dr of dirs) {
35
- const result = findAppDidFinishLaunchingWithOptions(path.join(dir, dr));
36
- if (result) return result;
37
- }
38
- return null;
47
+ for (const dr of dirs) {
48
+ const result = findAppDidFinishLaunchingWithOptions(path.join(dir, dr));
49
+ if (result) return result;
50
+ }
51
+ return null;
39
52
  }
40
53
 
41
- export function addCodeSnippetToProject(projPath: string, dsn: string): boolean {
42
- const appDelegate = findAppDidFinishLaunchingWithOptions(projPath);
43
- if (!appDelegate) {
44
- return false;
45
- }
54
+ export function addCodeSnippetToProject(
55
+ projPath: string,
56
+ dsn: string,
57
+ ): boolean {
58
+ const appDelegate = findAppDidFinishLaunchingWithOptions(projPath);
59
+ if (!appDelegate) {
60
+ return false;
61
+ }
46
62
 
47
- const fileContent = fs.readFileSync(appDelegate, 'utf8');
48
- const isSwift = appDelegate.toLowerCase().endsWith(".swift");
49
- const appLaunchRegex = isSwift ? swiftAppLaunchRegex : objcAppLaunchRegex;
50
- const importStatement = isSwift ? "import Sentry\n" : "@import Sentry;\n";
51
- const checkForSentryInit = isSwift ? "SentrySDK.start" : "[SentrySDK start";
52
- let codeSnippet = isSwift ? templates.getSwiftSnippet(dsn) : templates.getObjcSnippet(dsn);
63
+ const fileContent = fs.readFileSync(appDelegate, 'utf8');
64
+ const isSwift = appDelegate.toLowerCase().endsWith('.swift');
65
+ const appLaunchRegex = isSwift ? swiftAppLaunchRegex : objcAppLaunchRegex;
66
+ const importStatement = isSwift ? 'import Sentry\n' : '@import Sentry;\n';
67
+ const checkForSentryInit = isSwift ? 'SentrySDK.start' : '[SentrySDK start';
68
+ let codeSnippet = isSwift
69
+ ? templates.getSwiftSnippet(dsn)
70
+ : templates.getObjcSnippet(dsn);
53
71
 
54
- Sentry.setTag("code-language", isSwift ? "swift" : "objc");
55
- Sentry.setTag("ui-engine", swiftUIRegex.test(fileContent) ? "swiftui" : "uikit");
72
+ Sentry.setTag('code-language', isSwift ? 'swift' : 'objc');
73
+ Sentry.setTag(
74
+ 'ui-engine',
75
+ swiftUIRegex.test(fileContent) ? 'swiftui' : 'uikit',
76
+ );
56
77
 
57
- if (fileContent.includes(checkForSentryInit)) {
58
- //already initialized
59
- return true;
60
- }
78
+ if (fileContent.includes(checkForSentryInit)) {
79
+ //already initialized
80
+ return true;
81
+ }
61
82
 
62
- let match = appLaunchRegex.exec(fileContent);
63
- if (!match) {
64
- const swiftUIMatch = swiftUIRegex.exec(fileContent)
65
- if (!swiftUIMatch) {
66
- return false;
67
- }
68
- //Is SwiftUI with no init
69
- match = swiftUIMatch;
70
- codeSnippet = ` init() {\n${codeSnippet} }`;
83
+ let match = appLaunchRegex.exec(fileContent);
84
+ if (!match) {
85
+ const swiftUIMatch = swiftUIRegex.exec(fileContent);
86
+ if (!swiftUIMatch) {
87
+ return false;
71
88
  }
89
+ //Is SwiftUI with no init
90
+ match = swiftUIMatch;
91
+ codeSnippet = ` init() {\n${codeSnippet} }`;
92
+ }
72
93
 
73
- const insertIndex = match.index + match[0].length;
74
- const newFileContent = (fileContent.indexOf(importStatement) >= 0 ? "" : importStatement) +
75
- fileContent.slice(0, insertIndex) + "\n" +
76
- codeSnippet +
77
- fileContent.slice(insertIndex);
78
- fs.writeFileSync(appDelegate, newFileContent, 'utf8');
94
+ const insertIndex = match.index + match[0].length;
95
+ const newFileContent =
96
+ (fileContent.indexOf(importStatement) >= 0 ? '' : importStatement) +
97
+ fileContent.slice(0, insertIndex) +
98
+ '\n' +
99
+ codeSnippet +
100
+ fileContent.slice(insertIndex);
101
+ fs.writeFileSync(appDelegate, newFileContent, 'utf8');
79
102
 
80
- return true;
81
- }
103
+ return true;
104
+ }
@@ -0,0 +1,160 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as templates from './templates';
4
+ import { askForItemSelection } from '../utils/clack-utils';
5
+
6
+ export function fastFile(projectPath: string): string | null {
7
+ const fastlanePath = path.join(projectPath, 'fastlane', 'Fastfile');
8
+ return fs.existsSync(fastlanePath) ? fastlanePath : null;
9
+ }
10
+
11
+ function findIOSPlatform(
12
+ content: string,
13
+ ): { index: number; length: number } | null {
14
+ const platformRegex = /^ *platform\s+:([^ ]+)[^\n]*\n/gim;
15
+ let match = platformRegex.exec(content);
16
+ if (!match) {
17
+ // No platform found, treat whole file as one platform.
18
+ return { index: 0, length: content.length };
19
+ }
20
+
21
+ let index = -1;
22
+ while (match) {
23
+ if (match[1] === 'ios') {
24
+ index = match.index + match[0].length;
25
+ break;
26
+ }
27
+ match = platformRegex.exec(content);
28
+ }
29
+
30
+ if (index === -1) {
31
+ return null;
32
+ }
33
+
34
+ //After finding the platform, we need to find the end of the platform block.
35
+ //This solution has the assumption that the file is well formed,
36
+ //which is not a perfect solution, but it's good enough assumption.
37
+ const platformEndRegex = /^end[^\n]*/gim;
38
+ match = platformEndRegex.exec(content.slice(index));
39
+ if (!match) {
40
+ return null;
41
+ }
42
+
43
+ return { index, length: match.index };
44
+ }
45
+
46
+ function findLanes(
47
+ content: string,
48
+ ): { index: number; length: number; name: string }[] | null {
49
+ const laneRegex = /^ {2}lane\s+:([^ ]+)[^\n]*\n/gim;
50
+ let match = laneRegex.exec(content);
51
+ if (!match) {
52
+ return null;
53
+ }
54
+
55
+ const lanes: { index: number; length: number; name: string }[] = [];
56
+ while (match) {
57
+ const laneEnd = /^ {2}end/m.exec(
58
+ content.slice(match.index + match[0].length),
59
+ );
60
+ if (laneEnd === null) {
61
+ return null;
62
+ }
63
+ lanes.push({
64
+ index: match.index + match[0].length,
65
+ length: laneEnd.index,
66
+ name: match[1],
67
+ });
68
+ match = laneRegex.exec(content);
69
+ }
70
+ return lanes;
71
+ }
72
+
73
+ function addSentryToLane(
74
+ content: string,
75
+ lane: { index: number; length: number; name: string },
76
+ org: string,
77
+ project: string,
78
+ token: string,
79
+ ): string {
80
+ const laneContent = content.slice(lane.index, lane.index + lane.length);
81
+ const sentryCLIMatch = /sentry_cli\s*\([^)]+\)/gim.exec(laneContent);
82
+ if (sentryCLIMatch) {
83
+ // Sentry already added to lane. Update it.
84
+ return (
85
+ content.slice(0, sentryCLIMatch.index + lane.index) +
86
+ templates.getFastlaneSnippet(org, project, token).trim() +
87
+ content.slice(
88
+ sentryCLIMatch.index + sentryCLIMatch[0].length + lane.index,
89
+ )
90
+ );
91
+ }
92
+
93
+ // Sentry not added to lane. Add it.
94
+ return (
95
+ content.slice(0, lane.index + lane.length) +
96
+ '\n' +
97
+ templates.getFastlaneSnippet(org, project, token) +
98
+ '\n' +
99
+ content.slice(lane.index + lane.length)
100
+ );
101
+ }
102
+
103
+ export async function addSentryToFastlane(
104
+ projectPath: string,
105
+ org: string,
106
+ project: string,
107
+ token: string,
108
+ ): Promise<boolean> {
109
+ const fastFilePath = fastFile(projectPath);
110
+ if (!fastFilePath) {
111
+ return false;
112
+ }
113
+
114
+ const fileContent = fs.readFileSync(fastFilePath, 'utf8');
115
+ const platform = findIOSPlatform(fileContent);
116
+ if (!platform) {
117
+ return false;
118
+ }
119
+
120
+ const platformContent = fileContent.slice(
121
+ platform.index,
122
+ platform.index + platform.length,
123
+ );
124
+ const lanes = findLanes(platformContent);
125
+ lanes?.forEach((l) => (l.index += platform.index));
126
+
127
+ if (!lanes || lanes.length === 0) {
128
+ return false;
129
+ }
130
+
131
+ let newFileContent: string | undefined;
132
+ if (lanes.length === 1) {
133
+ newFileContent = addSentryToLane(
134
+ fileContent,
135
+ lanes[0],
136
+ org,
137
+ project,
138
+ token,
139
+ );
140
+ } else {
141
+ const laneNames = lanes.map((l) => l.name);
142
+ const selectedLane = await askForItemSelection(
143
+ laneNames,
144
+ 'Select lane to add Sentry to:',
145
+ );
146
+ if (selectedLane === undefined) {
147
+ return false;
148
+ }
149
+ newFileContent = addSentryToLane(
150
+ fileContent,
151
+ lanes[selectedLane.index],
152
+ org,
153
+ project,
154
+ token,
155
+ );
156
+ }
157
+
158
+ fs.writeFileSync(fastFilePath, newFileContent, 'utf8');
159
+ return true;
160
+ }
@@ -1,17 +1,20 @@
1
1
  export function getRunScriptTemplate(
2
- orgSlug: string,
3
- projectSlug: string,
4
- apiKey: string,
5
- uploadSource = true,
2
+ orgSlug: string,
3
+ projectSlug: string,
4
+ apiKey: string,
5
+ uploadSource = true,
6
6
  ): string {
7
- // eslint-disable-next-line no-useless-escape
8
- return `# This script is responsable to upload debug symbols and source context for Sentry.\\nif which sentry-cli >/dev/null; then\\nexport SENTRY_ORG=${orgSlug}\\nexport SENTRY_PROJECT=${projectSlug}\\nexport SENTRY_AUTH_TOKEN=${apiKey}\\nERROR=$(sentry-cli debug-files upload ${uploadSource ? "--include-sources " : ""}\"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null)\\nif [ ! $? -eq 0 ]; then\\necho \"warning: sentry-cli - $ERROR\"\\nfi\\nelse\\necho \"warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases\"\\nfi\\n`;
7
+ // eslint-disable-next-line no-useless-escape
8
+ return `# This script is responsable to upload debug symbols and source context for Sentry.\\nif which sentry-cli >/dev/null; then\\nexport SENTRY_ORG=${orgSlug}\\nexport SENTRY_PROJECT=${projectSlug}\\nexport SENTRY_AUTH_TOKEN=${apiKey}\\nERROR=$(sentry-cli debug-files upload ${
9
+ uploadSource ? '--include-sources ' : ''
10
+ }"$DWARF_DSYM_FOLDER_PATH" 2>&1 >/dev/null)\\nif [ ! $? -eq 0 ]; then\\necho "warning: sentry-cli - $ERROR"\\nfi\\nelse\\necho "warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases"\\nfi\\n`;
9
11
  }
10
12
 
11
- export const scriptInputPath = "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"";
13
+ export const scriptInputPath =
14
+ '"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}"';
12
15
 
13
16
  export function getSwiftSnippet(dsn: string): string {
14
- return ` SentrySDK.start { options in
17
+ return ` SentrySDK.start { options in
15
18
  options.dsn = "${dsn}"
16
19
  options.debug = true // Enabled debug when first installing is always helpful
17
20
  options.enableTracing = true
@@ -25,7 +28,7 @@ export function getSwiftSnippet(dsn: string): string {
25
28
  }
26
29
 
27
30
  export function getObjcSnippet(dsn: string): string {
28
- return ` [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {
31
+ return ` [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {
29
32
  options.dsn = @"${dsn}";
30
33
  options.debug = YES; // Enabled debug when first installing is always helpful
31
34
  options.enableTracing = YES;
@@ -36,4 +39,17 @@ export function getObjcSnippet(dsn: string): string {
36
39
  }];
37
40
  //Remove the next line after confirming that your Sentry integration is working.
38
41
  [SentrySDK captureMessage:@"This app uses Sentry!"];\n`;
39
- }
42
+ }
43
+
44
+ export function getFastlaneSnippet(
45
+ org: string,
46
+ project: string,
47
+ token: string,
48
+ ): string {
49
+ return ` sentry_cli(
50
+ auth_token: '${token}',
51
+ org_slug: '${org}',
52
+ project_slug: '${project}',
53
+ include_sources: true
54
+ )`;
55
+ }
@@ -3,145 +3,162 @@
3
3
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
4
  /* eslint-disable @typescript-eslint/no-unsafe-call */
5
5
  /* eslint-disable @typescript-eslint/no-unused-vars */
6
- import { SentryCli } from '../../lib/Helper/SentryCli';
7
- // @ts-ignore - clack is ESM and TS complains about that. It works though
8
- import clack from '@clack/prompts';
9
- import chalk from 'chalk';
10
6
  import * as fs from 'fs';
11
- import * as path from 'path';
7
+ import { SentryProjectData } from '../utils/types';
12
8
  import * as templates from './templates';
13
9
  const xcode = require('xcode');
14
10
 
15
- import { SentryProjectData } from '../utils/clack-utils';
16
11
  /* eslint-enable @typescript-eslint/no-unused-vars */
17
12
 
18
13
  function setDebugInformationFormat(proj: any): void {
19
- const xcObjects = proj.hash.project.objects;
20
- const target = proj.getFirstTarget().firstTarget;
21
-
22
- xcObjects.XCConfigurationList[target.buildConfigurationList].buildConfigurations.forEach((buildConfig: { value: string }) => {
23
- xcObjects.XCBuildConfiguration[buildConfig.value].buildSettings.DEBUG_INFORMATION_FORMAT = "\"dwarf-with-dsym\"";
24
- });
14
+ const xcObjects = proj.hash.project.objects;
15
+ const target = proj.getFirstTarget().firstTarget;
16
+
17
+ xcObjects.XCConfigurationList[
18
+ target.buildConfigurationList
19
+ ].buildConfigurations.forEach((buildConfig: { value: string }) => {
20
+ xcObjects.XCBuildConfiguration[
21
+ buildConfig.value
22
+ ].buildSettings.DEBUG_INFORMATION_FORMAT = '"dwarf-with-dsym"';
23
+ });
25
24
  }
26
25
 
27
26
  function addSentrySPM(proj: any): void {
28
- const xcObjects = proj.hash.project.objects;
29
-
30
- const sentryFrameworkUUID = proj.generateUuid() as string;
31
- const sentrySPMUUID = proj.generateUuid() as string;
32
-
33
- //Check whether xcObjects already have sentry framework
34
- if (xcObjects.PBXFrameworksBuildPhase) {
35
- for (const key in xcObjects.PBXFrameworksBuildPhase || {}) {
36
- if (!key.endsWith("_comment")) {
37
- const frameworks = xcObjects.PBXFrameworksBuildPhase[key].files;
38
- for (const framework of frameworks) {
39
- if (framework.comment === "Sentry in Frameworks") {
40
- return;
41
- }
42
- }
43
- }
44
- }
45
- }
27
+ const xcObjects = proj.hash.project.objects;
46
28
 
47
- xcObjects.PBXBuildFile[sentryFrameworkUUID] = {
48
- isa: "PBXBuildFile",
49
- productRef: sentrySPMUUID,
50
- productRef_comment: "Sentry",
51
- };
52
- xcObjects.PBXBuildFile[sentryFrameworkUUID + "_comment"] = "Sentry in Frameworks";
29
+ const sentryFrameworkUUID = proj.generateUuid() as string;
30
+ const sentrySPMUUID = proj.generateUuid() as string;
53
31
 
32
+ //Check whether xcObjects already have sentry framework
33
+ if (xcObjects.PBXFrameworksBuildPhase) {
54
34
  for (const key in xcObjects.PBXFrameworksBuildPhase || {}) {
55
- if (!key.endsWith("_comment")) {
56
- const frameworks = xcObjects.PBXFrameworksBuildPhase[key].files;
57
- frameworks.push({
58
- value: sentryFrameworkUUID,
59
- comment: "Sentry in Frameworks",
60
- });
35
+ if (!key.endsWith('_comment')) {
36
+ const frameworks = xcObjects.PBXFrameworksBuildPhase[key].files;
37
+ for (const framework of frameworks) {
38
+ if (framework.comment === 'Sentry in Frameworks') {
39
+ return;
40
+ }
61
41
  }
42
+ }
62
43
  }
63
-
64
- const target = proj.getFirstTarget().firstTarget;
65
- if (!target.packageProductDependencies) {
66
- target.packageProductDependencies = [];
44
+ }
45
+
46
+ xcObjects.PBXBuildFile[sentryFrameworkUUID] = {
47
+ isa: 'PBXBuildFile',
48
+ productRef: sentrySPMUUID,
49
+ productRef_comment: 'Sentry',
50
+ };
51
+ xcObjects.PBXBuildFile[sentryFrameworkUUID + '_comment'] =
52
+ 'Sentry in Frameworks';
53
+
54
+ for (const key in xcObjects.PBXFrameworksBuildPhase || {}) {
55
+ if (!key.endsWith('_comment')) {
56
+ const frameworks = xcObjects.PBXFrameworksBuildPhase[key].files;
57
+ frameworks.push({
58
+ value: sentryFrameworkUUID,
59
+ comment: 'Sentry in Frameworks',
60
+ });
67
61
  }
68
- target.packageProductDependencies.push({
69
- value: sentrySPMUUID,
70
- comment: "Sentry",
71
- });
72
-
73
- const sentrySwiftPackageUUID = proj.generateUuid() as string;
74
- const xcProject = proj.getFirstProject().firstProject;
75
- if (!xcProject.packageReferences) {
76
- xcProject.packageReferences = [];
77
- }
78
- xcProject.packageReferences.push({
79
- value: sentrySwiftPackageUUID,
80
- comment: "XCRemoteSwiftPackageReference \"sentry-cocoa\"",
81
- });
82
-
83
- xcObjects.XCRemoteSwiftPackageReference = {};
84
- xcObjects.XCRemoteSwiftPackageReference[sentrySwiftPackageUUID] = {
85
- isa: "XCRemoteSwiftPackageReference",
86
- repositoryURL: "\"https://github.com/getsentry/sentry-cocoa/\"",
87
- requirement: {
88
- kind: "upToNextMajorVersion",
89
- minimumVersion: "8.0.0",
90
- }
91
- };
92
- xcObjects.XCRemoteSwiftPackageReference[sentrySwiftPackageUUID + "_comment"] = "XCRemoteSwiftPackageReference \"sentry-cocoa\"";
93
-
94
- xcObjects.XCSwiftPackageProductDependency = {};
95
- xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID] =
96
- {
97
- isa: "XCSwiftPackageProductDependency",
98
- package: sentrySwiftPackageUUID,
99
- package_comment: "XCRemoteSwiftPackageReference \"sentry-cocoa\"",
100
- productName: "Sentry",
101
- };
102
- xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID + "_comment"] = "Sentry";
62
+ }
63
+
64
+ const target = proj.getFirstTarget().firstTarget;
65
+ if (!target.packageProductDependencies) {
66
+ target.packageProductDependencies = [];
67
+ }
68
+ target.packageProductDependencies.push({
69
+ value: sentrySPMUUID,
70
+ comment: 'Sentry',
71
+ });
72
+
73
+ const sentrySwiftPackageUUID = proj.generateUuid() as string;
74
+ const xcProject = proj.getFirstProject().firstProject;
75
+ if (!xcProject.packageReferences) {
76
+ xcProject.packageReferences = [];
77
+ }
78
+ xcProject.packageReferences.push({
79
+ value: sentrySwiftPackageUUID,
80
+ comment: 'XCRemoteSwiftPackageReference "sentry-cocoa"',
81
+ });
82
+
83
+ xcObjects.XCRemoteSwiftPackageReference = {};
84
+ xcObjects.XCRemoteSwiftPackageReference[sentrySwiftPackageUUID] = {
85
+ isa: 'XCRemoteSwiftPackageReference',
86
+ repositoryURL: '"https://github.com/getsentry/sentry-cocoa/"',
87
+ requirement: {
88
+ kind: 'upToNextMajorVersion',
89
+ minimumVersion: '8.0.0',
90
+ },
91
+ };
92
+ xcObjects.XCRemoteSwiftPackageReference[sentrySwiftPackageUUID + '_comment'] =
93
+ 'XCRemoteSwiftPackageReference "sentry-cocoa"';
94
+
95
+ xcObjects.XCSwiftPackageProductDependency = {};
96
+ xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID] = {
97
+ isa: 'XCSwiftPackageProductDependency',
98
+ package: sentrySwiftPackageUUID,
99
+ package_comment: 'XCRemoteSwiftPackageReference "sentry-cocoa"',
100
+ productName: 'Sentry',
101
+ };
102
+ xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID + '_comment'] =
103
+ 'Sentry';
103
104
  }
104
105
 
105
- function addUploadSymbolsScript(xcodeProject: any, sentryProject: SentryProjectData, apiKeys: { token: string }, uploadSource = true): void {
106
- const xcObjects = xcodeProject.hash.project.objects;
107
-
108
- for (const scriptKey in xcObjects.PBXShellScriptBuildPhase || {}) {
109
- if (!scriptKey.endsWith("_comment")) {
110
- const script = xcObjects.PBXShellScriptBuildPhase[scriptKey].shellScript;
111
- //Sentry script already exists, update it
112
- if (script.includes("sentry-cli")) {
113
- delete xcObjects.PBXShellScriptBuildPhase[scriptKey];
114
- delete xcObjects.PBXShellScriptBuildPhase[scriptKey + "_comment"];
115
- break;
116
- }
117
- }
106
+ function addUploadSymbolsScript(
107
+ xcodeProject: any,
108
+ sentryProject: SentryProjectData,
109
+ apiKeys: { token: string },
110
+ uploadSource = true,
111
+ ): void {
112
+ const xcObjects = xcodeProject.hash.project.objects;
113
+
114
+ for (const scriptKey in xcObjects.PBXShellScriptBuildPhase || {}) {
115
+ if (!scriptKey.endsWith('_comment')) {
116
+ const script = xcObjects.PBXShellScriptBuildPhase[scriptKey].shellScript;
117
+ //Sentry script already exists, update it
118
+ if (script.includes('sentry-cli')) {
119
+ delete xcObjects.PBXShellScriptBuildPhase[scriptKey];
120
+ delete xcObjects.PBXShellScriptBuildPhase[scriptKey + '_comment'];
121
+ break;
122
+ }
118
123
  }
124
+ }
119
125
 
120
- xcodeProject.addBuildPhase(
121
- [],
122
- 'PBXShellScriptBuildPhase',
123
- 'Upload Debug Symbols to Sentry',
124
- null,
125
- {
126
- inputFileListPaths: [],
127
- outputFileListPaths: [],
128
- inputPaths: [templates.scriptInputPath],
129
- shellPath: '/bin/sh',
130
- shellScript: templates.getRunScriptTemplate(sentryProject.organization.slug, sentryProject.slug, apiKeys.token, uploadSource)
131
- },
132
- );
126
+ xcodeProject.addBuildPhase(
127
+ [],
128
+ 'PBXShellScriptBuildPhase',
129
+ 'Upload Debug Symbols to Sentry',
130
+ null,
131
+ {
132
+ inputFileListPaths: [],
133
+ outputFileListPaths: [],
134
+ inputPaths: [templates.scriptInputPath],
135
+ shellPath: '/bin/sh',
136
+ shellScript: templates.getRunScriptTemplate(
137
+ sentryProject.organization.slug,
138
+ sentryProject.slug,
139
+ apiKeys.token,
140
+ uploadSource,
141
+ ),
142
+ },
143
+ );
133
144
  }
134
145
 
135
- export function updateXcodeProject(projectPath: string, sentryProject: SentryProjectData, apiKeys: { token: string }, addSPMReference: boolean, uploadSource = true): void {
136
- const proj = xcode.project(projectPath);
137
- proj.parseSync();
138
- addUploadSymbolsScript(proj, sentryProject, apiKeys, uploadSource);
139
- if (uploadSource) {
140
- setDebugInformationFormat(proj);
141
- }
142
- if (addSPMReference) {
143
- addSentrySPM(proj);
144
- }
145
- const newContent = proj.writeSync();
146
- fs.writeFileSync(projectPath, newContent);
147
- }
146
+ export function updateXcodeProject(
147
+ projectPath: string,
148
+ sentryProject: SentryProjectData,
149
+ apiKeys: { token: string },
150
+ addSPMReference: boolean,
151
+ uploadSource = true,
152
+ ): void {
153
+ const proj = xcode.project(projectPath);
154
+ proj.parseSync();
155
+ addUploadSymbolsScript(proj, sentryProject, apiKeys, uploadSource);
156
+ if (uploadSource) {
157
+ setDebugInformationFormat(proj);
158
+ }
159
+ if (addSPMReference) {
160
+ addSentrySPM(proj);
161
+ }
162
+ const newContent = proj.writeSync();
163
+ fs.writeFileSync(projectPath, newContent);
164
+ }