@sentry/wizard 4.7.0 → 4.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 (175) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +19 -19
  3. package/dist/e2e-tests/tests/angular-17.test.d.ts +1 -0
  4. package/dist/e2e-tests/tests/angular-17.test.js +196 -0
  5. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -0
  6. package/dist/e2e-tests/tests/angular-19.test.d.ts +1 -0
  7. package/dist/e2e-tests/tests/angular-19.test.js +194 -0
  8. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -0
  9. package/dist/e2e-tests/tests/expo.test.d.ts +1 -0
  10. package/dist/e2e-tests/tests/expo.test.js +103 -0
  11. package/dist/e2e-tests/tests/expo.test.js.map +1 -0
  12. package/dist/e2e-tests/tests/help-message.test.js +2 -2
  13. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  14. package/dist/e2e-tests/tests/react-native.test.d.ts +1 -0
  15. package/dist/e2e-tests/tests/react-native.test.js +132 -0
  16. package/dist/e2e-tests/tests/react-native.test.js.map +1 -0
  17. package/dist/e2e-tests/tests/remix.test.js +4 -4
  18. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  19. package/dist/e2e-tests/tests/sveltekit.test.js +2 -2
  20. package/dist/e2e-tests/tests/sveltekit.test.js.map +1 -1
  21. package/dist/e2e-tests/utils/index.d.ts +7 -0
  22. package/dist/e2e-tests/utils/index.js +32 -7
  23. package/dist/e2e-tests/utils/index.js.map +1 -1
  24. package/dist/lib/Constants.d.ts +1 -0
  25. package/dist/lib/Constants.js +3 -0
  26. package/dist/lib/Constants.js.map +1 -1
  27. package/dist/lib/Helper/SentryCli.d.ts +0 -11
  28. package/dist/lib/Helper/SentryCli.js +0 -52
  29. package/dist/lib/Helper/SentryCli.js.map +1 -1
  30. package/dist/src/android/templates.js +2 -0
  31. package/dist/src/android/templates.js.map +1 -1
  32. package/dist/src/angular/angular-wizard.d.ts +3 -0
  33. package/dist/src/angular/angular-wizard.js +186 -0
  34. package/dist/src/angular/angular-wizard.js.map +1 -0
  35. package/dist/src/angular/codemods/app-config.d.ts +3 -0
  36. package/dist/src/angular/codemods/app-config.js +211 -0
  37. package/dist/src/angular/codemods/app-config.js.map +1 -0
  38. package/dist/src/angular/codemods/main.d.ts +20 -0
  39. package/dist/src/angular/codemods/main.js +62 -0
  40. package/dist/src/angular/codemods/main.js.map +1 -0
  41. package/dist/src/angular/codemods/sourcemaps.d.ts +21 -0
  42. package/dist/src/angular/codemods/sourcemaps.js +94 -0
  43. package/dist/src/angular/codemods/sourcemaps.js.map +1 -0
  44. package/dist/src/angular/example-component.d.ts +8 -0
  45. package/dist/src/angular/example-component.js +286 -0
  46. package/dist/src/angular/example-component.js.map +1 -0
  47. package/dist/src/angular/sdk-setup.d.ts +6 -0
  48. package/dist/src/angular/sdk-setup.js +99 -0
  49. package/dist/src/angular/sdk-setup.js.map +1 -0
  50. package/dist/src/apple/code-tools.d.ts +4 -2
  51. package/dist/src/apple/code-tools.js +21 -11
  52. package/dist/src/apple/code-tools.js.map +1 -1
  53. package/dist/src/apple/inject-code-snippet.js +5 -3
  54. package/dist/src/apple/inject-code-snippet.js.map +1 -1
  55. package/dist/src/apple/macos-system-helper.d.ts +5 -0
  56. package/dist/src/apple/macos-system-helper.js +86 -0
  57. package/dist/src/apple/macos-system-helper.js.map +1 -0
  58. package/dist/src/apple/templates.js +10 -0
  59. package/dist/src/apple/templates.js.map +1 -1
  60. package/dist/src/apple/xcode-manager.d.ts +237 -11
  61. package/dist/src/apple/xcode-manager.js +736 -65
  62. package/dist/src/apple/xcode-manager.js.map +1 -1
  63. package/dist/src/apple/xcode-project-object-with-id.d.ts +5 -0
  64. package/dist/src/apple/xcode-project-object-with-id.js +3 -0
  65. package/dist/src/apple/xcode-project-object-with-id.js.map +1 -0
  66. package/dist/src/flutter/flutter-wizard.js +10 -2
  67. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  68. package/dist/src/flutter/templates.js +7 -1
  69. package/dist/src/flutter/templates.js.map +1 -1
  70. package/dist/src/nextjs/nextjs-wizard.js +27 -15
  71. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  72. package/dist/src/nextjs/templates.js +56 -7
  73. package/dist/src/nextjs/templates.js.map +1 -1
  74. package/dist/src/nuxt/nuxt-wizard.js +1 -3
  75. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  76. package/dist/src/nuxt/templates.js +30 -0
  77. package/dist/src/nuxt/templates.js.map +1 -1
  78. package/dist/src/react-native/expo-env-file.js +5 -0
  79. package/dist/src/react-native/expo-env-file.js.map +1 -1
  80. package/dist/src/react-native/expo-metro.js +22 -6
  81. package/dist/src/react-native/expo-metro.js.map +1 -1
  82. package/dist/src/react-native/expo.js +11 -1
  83. package/dist/src/react-native/expo.js.map +1 -1
  84. package/dist/src/react-native/glob.js +14 -4
  85. package/dist/src/react-native/glob.js.map +1 -1
  86. package/dist/src/react-native/gradle.js +14 -4
  87. package/dist/src/react-native/gradle.js.map +1 -1
  88. package/dist/src/react-native/javascript.d.ts +9 -4
  89. package/dist/src/react-native/javascript.js +52 -23
  90. package/dist/src/react-native/javascript.js.map +1 -1
  91. package/dist/src/react-native/metro.d.ts +1 -1
  92. package/dist/src/react-native/metro.js +36 -4
  93. package/dist/src/react-native/metro.js.map +1 -1
  94. package/dist/src/react-native/react-native-wizard.d.ts +4 -0
  95. package/dist/src/react-native/react-native-wizard.js +32 -4
  96. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  97. package/dist/src/react-native/xcode.js +29 -10
  98. package/dist/src/react-native/xcode.js.map +1 -1
  99. package/dist/src/remix/remix-wizard.js +1 -3
  100. package/dist/src/remix/remix-wizard.js.map +1 -1
  101. package/dist/src/remix/sdk-example.js +30 -1
  102. package/dist/src/remix/sdk-example.js.map +1 -1
  103. package/dist/src/remix/sdk-setup.js +11 -5
  104. package/dist/src/remix/sdk-setup.js.map +1 -1
  105. package/dist/src/run.d.ts +1 -1
  106. package/dist/src/run.js +5 -0
  107. package/dist/src/run.js.map +1 -1
  108. package/dist/src/sourcemaps/sourcemaps-wizard.d.ts +1 -1
  109. package/dist/src/sourcemaps/sourcemaps-wizard.js +35 -20
  110. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  111. package/dist/src/sourcemaps/tools/angular.d.ts +1 -0
  112. package/dist/src/sourcemaps/tools/angular.js +7 -7
  113. package/dist/src/sourcemaps/tools/angular.js.map +1 -1
  114. package/dist/src/sourcemaps/tools/sentry-cli.d.ts +5 -1
  115. package/dist/src/sourcemaps/tools/sentry-cli.js +6 -3
  116. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  117. package/dist/src/sourcemaps/tools/tsc.js +5 -1
  118. package/dist/src/sourcemaps/tools/tsc.js.map +1 -1
  119. package/dist/src/sourcemaps/tools/vite.js +4 -1
  120. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  121. package/dist/src/sourcemaps/tools/webpack.js +4 -1
  122. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  123. package/dist/src/sveltekit/sdk-example.js +1 -1
  124. package/dist/src/sveltekit/sdk-example.js.map +1 -1
  125. package/dist/src/sveltekit/sveltekit-wizard.js +3 -5
  126. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  127. package/dist/src/sveltekit/templates.js +28 -1
  128. package/dist/src/sveltekit/templates.js.map +1 -1
  129. package/dist/src/utils/clack/index.d.ts +13 -15
  130. package/dist/src/utils/clack/index.js +17 -50
  131. package/dist/src/utils/clack/index.js.map +1 -1
  132. package/dist/src/utils/git.d.ts +11 -0
  133. package/dist/src/utils/git.js +69 -0
  134. package/dist/src/utils/git.js.map +1 -0
  135. package/dist/src/utils/sentrycli-utils.js +13 -4
  136. package/dist/src/utils/sentrycli-utils.js.map +1 -1
  137. package/dist/src/version.d.ts +1 -1
  138. package/dist/src/version.js +1 -1
  139. package/dist/src/version.js.map +1 -1
  140. package/dist/test/angular/angular-wizard.test.d.ts +1 -0
  141. package/dist/test/angular/angular-wizard.test.js +27 -0
  142. package/dist/test/angular/angular-wizard.test.js.map +1 -0
  143. package/dist/test/angular/codemods/sourcemaps.test.d.ts +1 -0
  144. package/dist/test/angular/codemods/sourcemaps.test.js +237 -0
  145. package/dist/test/angular/codemods/sourcemaps.test.js.map +1 -0
  146. package/dist/test/angular/example-component.test.d.ts +1 -0
  147. package/dist/test/angular/example-component.test.js +105 -0
  148. package/dist/test/angular/example-component.test.js.map +1 -0
  149. package/dist/test/apple/code-tools.test.js +54 -35
  150. package/dist/test/apple/code-tools.test.js.map +1 -1
  151. package/dist/test/apple/configure-sentry-cli.test.d.ts +1 -0
  152. package/dist/test/apple/configure-sentry-cli.test.js +131 -0
  153. package/dist/test/apple/configure-sentry-cli.test.js.map +1 -0
  154. package/dist/test/apple/macos-system-helper-mocked.test.d.ts +1 -0
  155. package/dist/test/apple/macos-system-helper-mocked.test.js +46 -0
  156. package/dist/test/apple/macos-system-helper-mocked.test.js.map +1 -0
  157. package/dist/test/apple/macos-system-helper.test.d.ts +1 -0
  158. package/dist/test/apple/macos-system-helper.test.js +88 -0
  159. package/dist/test/apple/macos-system-helper.test.js.map +1 -0
  160. package/dist/test/apple/templates.test.js +10 -0
  161. package/dist/test/apple/templates.test.js.map +1 -1
  162. package/dist/test/apple/xcode-manager.test.js +745 -379
  163. package/dist/test/apple/xcode-manager.test.js.map +1 -1
  164. package/dist/test/flutter/templates.test.js +9 -0
  165. package/dist/test/flutter/templates.test.js.map +1 -1
  166. package/dist/test/react-native/javascript.test.js +119 -0
  167. package/dist/test/react-native/javascript.test.js.map +1 -1
  168. package/dist/test/react-native/metro.test.js +113 -0
  169. package/dist/test/react-native/metro.test.js.map +1 -1
  170. package/dist/test/remix/client-entry.test.js +10 -10
  171. package/dist/test/remix/client-entry.test.js.map +1 -1
  172. package/dist/test/utils/git.test.d.ts +1 -0
  173. package/dist/test/utils/git.test.js +70 -0
  174. package/dist/test/utils/git.test.js.map +1 -0
  175. package/package.json +1 -1
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.getSentryExampleComponentCode = exports.createExampleComponent = void 0;
30
+ const fs = __importStar(require("fs"));
31
+ const clack_1 = require("../utils/clack");
32
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
33
+ const clack = __importStar(require("@clack/prompts"));
34
+ const url_1 = require("../utils/url");
35
+ const chalk_1 = __importDefault(require("chalk"));
36
+ async function createExampleComponent(options) {
37
+ const componentName = 'sentry-example';
38
+ const appRootPath = './src/app';
39
+ let componentDirPath = appRootPath;
40
+ const hasAppRoot = fs.existsSync(appRootPath);
41
+ if (!hasAppRoot) {
42
+ componentDirPath = await (0, clack_1.abortIfCancelled)(clack.text({
43
+ message: 'Where should we create the example component?',
44
+ placeholder: appRootPath,
45
+ }));
46
+ }
47
+ if (!fs.existsSync(componentDirPath)) {
48
+ fs.mkdirSync(componentDirPath, { recursive: true });
49
+ }
50
+ const componentCode = getSentryExampleComponentCode(options);
51
+ const componentFilePath = `${componentDirPath}/${componentName}.component.ts`;
52
+ fs.writeFileSync(componentFilePath, componentCode);
53
+ clack.log.success(`Created example component at ${chalk_1.default.cyan(componentFilePath)}`);
54
+ const addComponentCodeSnippet = (0, clack_1.makeCodeSnippet)(true, (unchanged, plus) => unchanged(`${plus("import { SentryExample } from './sentry-example.component'")}
55
+
56
+ @Component({
57
+ selector: 'app-root',
58
+ standalone: true,
59
+ imports: [RouterOutlet, ${plus('SentryExample')}],
60
+ template: \`
61
+ <div class="app">
62
+ <h1>Your Application</h1>
63
+ ${plus('<app-sentry-example></app-sentry-example>')}
64
+ </div>
65
+ \`,
66
+ })
67
+ `));
68
+ await (0, clack_1.showCopyPasteInstructions)({
69
+ instructions: `Add the example component one of your pages or components (for example, in ${chalk_1.default.cyan('app.component.ts')}).`,
70
+ codeSnippet: addComponentCodeSnippet,
71
+ });
72
+ }
73
+ exports.createExampleComponent = createExampleComponent;
74
+ function getSentryExampleComponentCode(options) {
75
+ const issueStreamUrl = (0, url_1.getIssueStreamUrl)(options);
76
+ return `import { NgIf } from '@angular/common';
77
+ import { Component, OnInit } from '@angular/core';
78
+ import * as Sentry from '@sentry/angular';
79
+
80
+ /**
81
+ * This is just a very simple component that throws an example error.
82
+ * Feel free to delete this file once you verify that Sentry is working.
83
+ */
84
+
85
+ @Component({
86
+ selector: 'app-sentry-example',
87
+ standalone: true,
88
+ imports: [NgIf],
89
+ template: \`
90
+ <svg height="40" width="40" fill="none" xmlns="http://www.w3.org/2000/svg">
91
+ <path
92
+ d="M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z"
93
+ fill="currentcolor"
94
+ />
95
+ </svg>
96
+
97
+ <h1>app-sentry-example</h1>
98
+
99
+ <p class="description">
100
+ Click the button below, and view the sample error on the Sentry
101
+ <a
102
+ target="_blank"
103
+ href="${issueStreamUrl}"
104
+ >Issues Page</a
105
+ >. For more details about setting up Sentry,
106
+ <a
107
+ target="_blank"
108
+ href="https://docs.sentry.io/platforms/javascript/guides/angular/"
109
+ >read our docs</a
110
+ >.
111
+ </p>
112
+
113
+ <button (click)="throwError()">
114
+ <span>Throw Sample Error</span>
115
+ </button>
116
+
117
+ <div *ngIf="isConnected && sentError" class="success">
118
+ Sample error was sent to Sentry.
119
+ </div>
120
+ <div *ngIf="isConnected && !sentError" class="success_placeholder"></div>
121
+
122
+ <div *ngIf="!isConnected" class="connectivity-error">
123
+ <p>
124
+ The Sentry SDK is not able to reach Sentry right now - this may be due
125
+ to an adblocker. For more information, see
126
+ <a
127
+ target="_blank"
128
+ href="https://docs.sentry.io/platforms/javascript/guides/angular/troubleshooting/#the-sdk-is-not-sending-any-data"
129
+ >the troubleshooting guide</a
130
+ >.
131
+ </p>
132
+ </div>
133
+
134
+ <p class="description">
135
+ Adblockers will prevent errors from being sent to Sentry.
136
+ </p>
137
+ \`,
138
+ styles: \`
139
+ :host {
140
+ display: flex;
141
+ flex-direction: column;
142
+ justify-content: space-between;
143
+ align-items: center;
144
+ border: 2px solid #553DB8;
145
+ border-radius: 8px;
146
+ padding: 1em;
147
+ margin: 0.5em;
148
+ width: 500px;
149
+ height: 495px;
150
+ gap: 1em;
151
+ }
152
+
153
+ h1 {
154
+ padding: 0px 4px;
155
+ border-radius: 4px;
156
+ background-color: rgba(24, 20, 35, 0.03);
157
+ font-family: monospace;
158
+ font-size: 20px;
159
+ line-height: 1.2;
160
+ }
161
+
162
+ p {
163
+ margin: 0;
164
+ font-size: 20px;
165
+ }
166
+
167
+ a {
168
+ color: #6341F0;
169
+ text-decoration: underline;
170
+ cursor: pointer;
171
+
172
+ @media (prefers-color-scheme: dark) {
173
+ color: #B3A1FF;
174
+ }
175
+ }
176
+
177
+ button {
178
+ border-radius: 8px;
179
+ color: white;
180
+ cursor: pointer;
181
+ background-color: #553DB8;
182
+ border: none;
183
+ padding: 0;
184
+ margin-top: 4px;
185
+
186
+ & > span {
187
+ display: inline-block;
188
+ padding: 12px 16px;
189
+ border-radius: inherit;
190
+ font-size: 20px;
191
+ font-weight: bold;
192
+ line-height: 1;
193
+ background-color: #7553FF;
194
+ border: 1px solid #553DB8;
195
+ transform: translateY(-4px);
196
+ }
197
+
198
+ &:hover > span {
199
+ transform: translateY(-8px);
200
+ }
201
+
202
+ &:active > span {
203
+ transform: translateY(0);
204
+ }
205
+ }
206
+
207
+ .success {
208
+ padding: 12px 16px;
209
+ border-radius: 8px;
210
+ font-size: 20px;
211
+ line-height: 1;
212
+ background-color: #00F261;
213
+ border: 1px solid #00BF4D;
214
+ color: #181423;
215
+ }
216
+
217
+ .success_placeholder {
218
+ height: 46px;
219
+ }
220
+
221
+ .description {
222
+ text-align: center;
223
+ color: #6E6C75;
224
+ max-width: 500px;
225
+ line-height: 1.5;
226
+ font-size: 20px;
227
+
228
+ @media (prefers-color-scheme: dark) {
229
+ color: #A49FB5;
230
+ }
231
+ }
232
+
233
+ .connectivity-error {
234
+ padding: 12px 16px;
235
+ background-color: #E50045;
236
+ border-radius: 8px;
237
+ width: 500px;
238
+ color: #FFFFFF;
239
+ border: 1px solid #A80033;
240
+ text-align: center;
241
+ margin: 0;
242
+ max-width: 400px;
243
+ }
244
+
245
+ .connectivity-error a {
246
+ color: #FFFFFF;
247
+ text-decoration: underline;
248
+ }
249
+ \`,
250
+ })
251
+ export class SentryExample implements OnInit {
252
+ sentError = false;
253
+ isConnected = true;
254
+
255
+ async ngOnInit(): Promise<void> {
256
+ const res = await Sentry.diagnoseSdkConnectivity();
257
+ this.isConnected = res !== 'sentry-unreachable';
258
+ console.log({ res });
259
+ }
260
+
261
+ throwError() {
262
+ Sentry.startSpan(
263
+ {
264
+ name: 'Example Frontend Span',
265
+ op: 'test',
266
+ },
267
+ () => {
268
+ this.sentError = true;
269
+ throw new SentryExampleError(
270
+ 'This error was thrown by the Sentry example component.'
271
+ );
272
+ }
273
+ );
274
+ }
275
+ }
276
+
277
+ class SentryExampleError extends Error {
278
+ constructor(message: string | undefined) {
279
+ super(message);
280
+ this.name = 'SentryExampleError';
281
+ }
282
+ }
283
+ `;
284
+ }
285
+ exports.getSentryExampleComponentCode = getSentryExampleComponentCode;
286
+ //# sourceMappingURL=example-component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-component.js","sourceRoot":"","sources":["../../../src/angular/example-component.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,0CAIwB;AAExB,+EAA+E;AAC/E,sDAAwC;AACxC,sCAAiD;AACjD,kDAA0B;AAQnB,KAAK,UAAU,sBAAsB,CAAC,OAAgC;IAC3E,MAAM,aAAa,GAAG,gBAAgB,CAAC;IACvC,MAAM,WAAW,GAAG,WAAW,CAAC;IAEhC,IAAI,gBAAgB,GAAG,WAAW,CAAC;IACnC,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,EAAE;QACf,gBAAgB,GAAG,MAAM,IAAA,wBAAgB,EACvC,KAAK,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,+CAA+C;YACxD,WAAW,EAAE,WAAW;SACzB,CAAC,CACH,CAAC;KACH;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE;QACpC,EAAE,CAAC,SAAS,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;KACrD;IAED,MAAM,aAAa,GAAG,6BAA6B,CAAC,OAAO,CAAC,CAAC;IAE7D,MAAM,iBAAiB,GAAG,GAAG,gBAAgB,IAAI,aAAa,eAAe,CAAC;IAE9E,EAAE,CAAC,aAAa,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAEnD,KAAK,CAAC,GAAG,CAAC,OAAO,CACf,gCAAgC,eAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAChE,CAAC;IAEF,MAAM,uBAAuB,GAAG,IAAA,uBAAe,EAAC,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CACxE,SAAS,CAAC,GAAG,IAAI,CACf,4DAA4D,CAC7D;;;;;4BAKuB,IAAI,CAAC,eAAe,CAAC;;;;QAIzC,IAAI,CAAC,2CAA2C,CAAC;;;;CAIxD,CAAC,CACC,CAAC;IAEF,MAAM,IAAA,iCAAyB,EAAC;QAC9B,YAAY,EAAE,8EAA8E,eAAK,CAAC,IAAI,CACpG,kBAAkB,CACnB,IAAI;QACL,WAAW,EAAE,uBAAuB;KACrC,CAAC,CAAC;AACL,CAAC;AAtDD,wDAsDC;AAED,SAAgB,6BAA6B,CAC3C,OAAgC;IAEhC,MAAM,cAAc,GAAG,IAAA,uBAAiB,EAAC,OAAO,CAAC,CAAC;IAElD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA2BO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoL7B,CAAC;AACF,CAAC;AArND,sEAqNC","sourcesContent":["import * as fs from 'fs';\nimport {\n abortIfCancelled,\n makeCodeSnippet,\n showCopyPasteInstructions,\n} from '../utils/clack';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport { getIssueStreamUrl } from '../utils/url';\nimport chalk from 'chalk';\n\ninterface ExampleComponentOptions {\n url: string;\n orgSlug: string;\n projectId: string;\n}\n\nexport async function createExampleComponent(options: ExampleComponentOptions) {\n const componentName = 'sentry-example';\n const appRootPath = './src/app';\n\n let componentDirPath = appRootPath;\n const hasAppRoot = fs.existsSync(appRootPath);\n if (!hasAppRoot) {\n componentDirPath = await abortIfCancelled(\n clack.text({\n message: 'Where should we create the example component?',\n placeholder: appRootPath,\n }),\n );\n }\n\n if (!fs.existsSync(componentDirPath)) {\n fs.mkdirSync(componentDirPath, { recursive: true });\n }\n\n const componentCode = getSentryExampleComponentCode(options);\n\n const componentFilePath = `${componentDirPath}/${componentName}.component.ts`;\n\n fs.writeFileSync(componentFilePath, componentCode);\n\n clack.log.success(\n `Created example component at ${chalk.cyan(componentFilePath)}`,\n );\n\n const addComponentCodeSnippet = makeCodeSnippet(true, (unchanged, plus) =>\n unchanged(`${plus(\n \"import { SentryExample } from './sentry-example.component'\",\n )}\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [RouterOutlet, ${plus('SentryExample')}],\n template: \\`\n <div class=\"app\">\n <h1>Your Application</h1>\n ${plus('<app-sentry-example></app-sentry-example>')}\n </div>\n \\`,\n})\n`),\n );\n\n await showCopyPasteInstructions({\n instructions: `Add the example component one of your pages or components (for example, in ${chalk.cyan(\n 'app.component.ts',\n )}).`,\n codeSnippet: addComponentCodeSnippet,\n });\n}\n\nexport function getSentryExampleComponentCode(\n options: ExampleComponentOptions,\n) {\n const issueStreamUrl = getIssueStreamUrl(options);\n\n return `import { NgIf } from '@angular/common';\nimport { Component, OnInit } from '@angular/core';\nimport * as Sentry from '@sentry/angular';\n\n/**\n * This is just a very simple component that throws an example error.\n * Feel free to delete this file once you verify that Sentry is working.\n */\n\n@Component({\n selector: 'app-sentry-example',\n standalone: true,\n imports: [NgIf],\n template: \\`\n <svg height=\"40\" width=\"40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\"\n fill=\"currentcolor\"\n />\n </svg>\n\n <h1>app-sentry-example</h1>\n\n <p class=\"description\">\n Click the button below, and view the sample error on the Sentry\n <a\n target=\"_blank\"\n href=\"${issueStreamUrl}\"\n >Issues Page</a\n >. For more details about setting up Sentry,\n <a\n target=\"_blank\"\n href=\"https://docs.sentry.io/platforms/javascript/guides/angular/\"\n >read our docs</a\n >.\n </p>\n\n <button (click)=\"throwError()\">\n <span>Throw Sample Error</span>\n </button>\n\n <div *ngIf=\"isConnected && sentError\" class=\"success\">\n Sample error was sent to Sentry.\n </div>\n <div *ngIf=\"isConnected && !sentError\" class=\"success_placeholder\"></div>\n\n <div *ngIf=\"!isConnected\" class=\"connectivity-error\">\n <p>\n The Sentry SDK is not able to reach Sentry right now - this may be due\n to an adblocker. For more information, see\n <a\n target=\"_blank\"\n href=\"https://docs.sentry.io/platforms/javascript/guides/angular/troubleshooting/#the-sdk-is-not-sending-any-data\"\n >the troubleshooting guide</a\n >.\n </p>\n </div>\n\n <p class=\"description\">\n Adblockers will prevent errors from being sent to Sentry.\n </p>\n \\`,\n styles: \\`\n :host {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n align-items: center;\n border: 2px solid #553DB8;\n border-radius: 8px;\n padding: 1em;\n margin: 0.5em;\n width: 500px;\n height: 495px;\n gap: 1em;\n }\n\n h1 {\n padding: 0px 4px;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n } \n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .connectivity-error {\n padding: 12px 16px;\n background-color: #E50045;\n border-radius: 8px;\n width: 500px;\n color: #FFFFFF;\n border: 1px solid #A80033;\n text-align: center;\n margin: 0;\n max-width: 400px;\n }\n \n .connectivity-error a {\n color: #FFFFFF;\n text-decoration: underline;\n }\n \\`,\n})\nexport class SentryExample implements OnInit {\n sentError = false;\n isConnected = true;\n\n async ngOnInit(): Promise<void> {\n const res = await Sentry.diagnoseSdkConnectivity();\n this.isConnected = res !== 'sentry-unreachable';\n console.log({ res });\n }\n\n throwError() {\n Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test',\n },\n () => {\n this.sentError = true;\n throw new SentryExampleError(\n 'This error was thrown by the Sentry example component.'\n );\n }\n );\n }\n}\n\nclass SentryExampleError extends Error {\n constructor(message: string | undefined) {\n super(message);\n this.name = 'SentryExampleError';\n }\n}\n`;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { SemVer } from 'semver';
2
+ export declare function initializeSentryOnApplicationEntry(dsn: string, selectedFeatures: {
3
+ performance: boolean;
4
+ replay: boolean;
5
+ }): Promise<void>;
6
+ export declare function updateAppConfig(angularVersion: SemVer, isTracingEnabled: boolean): Promise<void>;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.updateAppConfig = exports.initializeSentryOnApplicationEntry = void 0;
31
+ // @ts-expect-error - magicast is ESM and TS complains about that. It works though
32
+ const magicast_1 = require("magicast");
33
+ const fs = __importStar(require("fs"));
34
+ const path = __importStar(require("path"));
35
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
36
+ const prompts_1 = __importDefault(require("@clack/prompts"));
37
+ const chalk_1 = __importDefault(require("chalk"));
38
+ const app_config_1 = require("./codemods/app-config");
39
+ const main_1 = require("./codemods/main");
40
+ const ast_utils_1 = require("../utils/ast-utils");
41
+ const Sentry = __importStar(require("@sentry/node"));
42
+ async function initializeSentryOnApplicationEntry(dsn, selectedFeatures) {
43
+ const appEntryFilename = 'main.ts';
44
+ const appEntryPath = path.join(process.cwd(), 'src', appEntryFilename);
45
+ const originalAppEntry = await (0, magicast_1.loadFile)(appEntryPath);
46
+ if ((0, ast_utils_1.hasSentryContent)(originalAppEntry.$ast)) {
47
+ prompts_1.default.log.warn(`File ${chalk_1.default.cyan(appEntryFilename)} already contains Sentry.
48
+ Skipping adding Sentry functionality to ${chalk_1.default.cyan(appEntryFilename)}.`);
49
+ return;
50
+ }
51
+ const updatedAppEntryMod = (0, main_1.updateAppEntryMod)(originalAppEntry, dsn, selectedFeatures);
52
+ try {
53
+ await (0, magicast_1.writeFile)(updatedAppEntryMod.$ast, appEntryPath);
54
+ }
55
+ catch (error) {
56
+ prompts_1.default.log.error(`Error while adding Sentry to ${chalk_1.default.cyan(appEntryFilename)}`);
57
+ prompts_1.default.log.warn(`Please refer to the documentation for manual setup:
58
+ ${chalk_1.default.underline('https://docs.sentry.io/platforms/javascript/guides/angular/#configure')}`);
59
+ return;
60
+ }
61
+ prompts_1.default.log.success(`Successfully initialized Sentry on ${chalk_1.default.cyan(appEntryFilename)}`);
62
+ }
63
+ exports.initializeSentryOnApplicationEntry = initializeSentryOnApplicationEntry;
64
+ async function updateAppConfig(angularVersion, isTracingEnabled) {
65
+ const appConfigFilename = 'app.config.ts';
66
+ const appConfigPath = path.join(process.cwd(), 'src', 'app', appConfigFilename);
67
+ if (!fs.existsSync(appConfigPath)) {
68
+ Sentry.setTag('angular-app-config-found', false);
69
+ prompts_1.default.log.warn(`File ${chalk_1.default.cyan(appConfigFilename)} not found. Skipping adding Sentry functionality.`);
70
+ prompts_1.default.log.warn(`Please refer to the documentation for manual setup:
71
+ ${chalk_1.default.underline('https://docs.sentry.io/platforms/javascript/guides/angular/#configure')}`);
72
+ return;
73
+ }
74
+ Sentry.setTag('angular-app-config-found', true);
75
+ const appConfig = await (0, magicast_1.loadFile)(appConfigPath);
76
+ if ((0, ast_utils_1.hasSentryContent)(appConfig.$ast)) {
77
+ prompts_1.default.log.warn(`File ${chalk_1.default.cyan(appConfigFilename)} already contains Sentry.
78
+ Skipping adding Sentry functionality to ${chalk_1.default.cyan(appConfigFilename)}.`);
79
+ return;
80
+ }
81
+ try {
82
+ const updatedAppConfigMod = (0, app_config_1.updateAppConfigMod)(appConfig, angularVersion, isTracingEnabled);
83
+ await (0, magicast_1.writeFile)(updatedAppConfigMod.$ast, appConfigPath);
84
+ }
85
+ catch (error) {
86
+ prompts_1.default.log.error(`Error while updating your app config ${chalk_1.default.cyan(appConfigFilename)}.`);
87
+ prompts_1.default.log.info(chalk_1.default.dim(typeof error === 'object' && error != null && 'toString' in error
88
+ ? error.toString()
89
+ : typeof error === 'string'
90
+ ? error
91
+ : ''));
92
+ prompts_1.default.log.warn(`Please refer to the documentation for manual setup:
93
+ ${chalk_1.default.underline('https://docs.sentry.io/platforms/javascript/guides/angular/#configure')}`);
94
+ return;
95
+ }
96
+ prompts_1.default.log.success(`Successfully updated your app config ${chalk_1.default.cyan(appConfigFilename)}`);
97
+ }
98
+ exports.updateAppConfig = updateAppConfig;
99
+ //# sourceMappingURL=sdk-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-setup.js","sourceRoot":"","sources":["../../../src/angular/sdk-setup.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { loadFile, writeFile } from 'magicast';\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport { updateAppConfigMod } from './codemods/app-config';\nimport { updateAppEntryMod } from './codemods/main';\nimport { hasSentryContent } from '../utils/ast-utils';\nimport * as Sentry from '@sentry/node';\n\nimport type { namedTypes as t } from 'ast-types';\nimport type { SemVer } from 'semver';\n\nexport async function initializeSentryOnApplicationEntry(\n dsn: string,\n selectedFeatures: {\n performance: boolean;\n replay: boolean;\n },\n): Promise<void> {\n const appEntryFilename = 'main.ts';\n const appEntryPath = path.join(process.cwd(), 'src', appEntryFilename);\n\n const originalAppEntry = await loadFile(appEntryPath);\n\n if (hasSentryContent(originalAppEntry.$ast as t.Program)) {\n clack.log.warn(\n `File ${chalk.cyan(appEntryFilename)} already contains Sentry.\nSkipping adding Sentry functionality to ${chalk.cyan(appEntryFilename)}.`,\n );\n\n return;\n }\n\n const updatedAppEntryMod = updateAppEntryMod(\n originalAppEntry,\n dsn,\n selectedFeatures,\n );\n\n try {\n await writeFile(updatedAppEntryMod.$ast, appEntryPath);\n } catch (error: unknown) {\n clack.log.error(\n `Error while adding Sentry to ${chalk.cyan(appEntryFilename)}`,\n );\n\n clack.log.warn(\n `Please refer to the documentation for manual setup:\n${chalk.underline(\n 'https://docs.sentry.io/platforms/javascript/guides/angular/#configure',\n)}`,\n );\n\n return;\n }\n\n clack.log.success(\n `Successfully initialized Sentry on ${chalk.cyan(appEntryFilename)}`,\n );\n}\n\nexport async function updateAppConfig(\n angularVersion: SemVer,\n isTracingEnabled: boolean,\n): Promise<void> {\n const appConfigFilename = 'app.config.ts';\n const appConfigPath = path.join(\n process.cwd(),\n 'src',\n 'app',\n appConfigFilename,\n );\n\n if (!fs.existsSync(appConfigPath)) {\n Sentry.setTag('angular-app-config-found', false);\n\n clack.log.warn(\n `File ${chalk.cyan(\n appConfigFilename,\n )} not found. Skipping adding Sentry functionality.`,\n );\n\n clack.log.warn(`Please refer to the documentation for manual setup:\n${chalk.underline(\n 'https://docs.sentry.io/platforms/javascript/guides/angular/#configure',\n)}`);\n\n return;\n }\n\n Sentry.setTag('angular-app-config-found', true);\n\n const appConfig = await loadFile(appConfigPath);\n\n if (hasSentryContent(appConfig.$ast as t.Program)) {\n clack.log.warn(\n `File ${chalk.cyan(appConfigFilename)} already contains Sentry.\n Skipping adding Sentry functionality to ${chalk.cyan(appConfigFilename)}.`,\n );\n\n return;\n }\n\n try {\n const updatedAppConfigMod = updateAppConfigMod(\n appConfig,\n angularVersion,\n isTracingEnabled,\n );\n\n await writeFile(updatedAppConfigMod.$ast, appConfigPath);\n } catch (error: unknown) {\n clack.log.error(\n `Error while updating your app config ${chalk.cyan(appConfigFilename)}.`,\n );\n\n clack.log.info(\n chalk.dim(\n typeof error === 'object' && error != null && 'toString' in error\n ? error.toString()\n : typeof error === 'string'\n ? error\n : '',\n ),\n );\n\n clack.log.warn(`Please refer to the documentation for manual setup:\n${chalk.underline(\n 'https://docs.sentry.io/platforms/javascript/guides/angular/#configure',\n)}`);\n\n return;\n }\n\n clack.log.success(\n `Successfully updated your app config ${chalk.cyan(appConfigFilename)}`,\n );\n}\n"]}
@@ -1,11 +1,13 @@
1
1
  declare function isAppDelegateFile(filePath: string): boolean;
2
- declare function findAppDidFinishLaunchingWithOptions(dir: string, files?: string[] | undefined): string | null;
3
- export declare function addCodeSnippetToProject(projPath: string, files: string[], dsn: string): boolean;
2
+ declare function findAppDidFinishLaunchingWithOptionsInDirectory(dir: string): string | null;
3
+ declare function findAppDidFinishLaunchingWithOptions(files: string[]): string | null;
4
+ export declare function addCodeSnippetToProject(files: string[], dsn: string): boolean;
4
5
  /**
5
6
  * Exported for testing purposes, but should not be used in other modules.
6
7
  */
7
8
  export declare let exportForTesting: {
8
9
  isAppDelegateFile: typeof isAppDelegateFile;
10
+ findAppDidFinishLaunchingWithOptionsInDirectory: typeof findAppDidFinishLaunchingWithOptionsInDirectory;
9
11
  findAppDidFinishLaunchingWithOptions: typeof findAppDidFinishLaunchingWithOptions;
10
12
  };
11
13
  export {};
@@ -30,29 +30,36 @@ const path = __importStar(require("path"));
30
30
  const templates = __importStar(require("./templates"));
31
31
  // @ts-expect-error - clack is ESM and TS complains about that. It works though
32
32
  const clack = __importStar(require("@clack/prompts"));
33
+ const debug_1 = require("../utils/debug");
33
34
  const swiftAppLaunchRegex = /(func\s+application\s*\(\s*_\s+application:\s*[^,]+,\s*didFinishLaunchingWithOptions[^,]+:\s*[^)]+\s*\)\s+->\s+Bool\s+{)|func\s+applicationDidFinishLaunching\s*\(\s*_\s+aNotification:\s+Notification\s*\)\s*{/im;
34
35
  const objcAppLaunchRegex = /-\s*\(\s*BOOL\s*\)\s*application:\s*\(\s*UIApplication\s*\*\s*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(\s*NSDictionary\s*\*\s*\)\s*launchOptions\s*{/im;
35
36
  const swiftUIRegex = /@main\s+struct[^:]+:\s*(SwiftUI\.)?App\s*{/im;
36
37
  function isAppDelegateFile(filePath) {
38
+ (0, debug_1.debug)('Checking if ' + filePath + ' is an AppDelegate file');
37
39
  const appLaunchRegex = filePath.toLowerCase().endsWith('.swift')
38
40
  ? swiftAppLaunchRegex
39
41
  : objcAppLaunchRegex;
40
42
  const fileContent = fs.readFileSync(filePath, 'utf8');
41
43
  return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
42
44
  }
43
- function findAppDidFinishLaunchingWithOptions(dir, files = undefined) {
44
- if (!files) {
45
- files = fs.readdirSync(dir);
46
- files = files.map((f) => path.join(dir, f));
47
- }
48
- //iterate over subdirectories later,
49
- //the appdelegate usually is in the top level
45
+ function findAppDidFinishLaunchingWithOptionsInDirectory(dir) {
46
+ (0, debug_1.debug)('Searching for AppDelegate in directory: ' + dir);
47
+ const files = fs.readdirSync(dir);
48
+ const filePaths = files.map((f) => path.join(dir, f));
49
+ return findAppDidFinishLaunchingWithOptions(filePaths);
50
+ }
51
+ function findAppDidFinishLaunchingWithOptions(files) {
52
+ (0, debug_1.debug)(`Searching for AppDelegate in ${files.length} files`);
53
+ // Iterate over subdirectories after iterating over files,
54
+ // because the AppDelegate is usually in the top level
50
55
  const dirs = [];
51
56
  for (const filePath of files) {
57
+ (0, debug_1.debug)('Checking file: ' + filePath);
52
58
  if (filePath.endsWith('.swift') ||
53
59
  filePath.endsWith('.m') ||
54
60
  filePath.endsWith('.mm')) {
55
61
  if (fs.existsSync(filePath) && isAppDelegateFile(filePath)) {
62
+ (0, debug_1.debug)('Found AppDelegate in ' + filePath);
56
63
  return filePath;
57
64
  }
58
65
  }
@@ -65,14 +72,16 @@ function findAppDidFinishLaunchingWithOptions(dir, files = undefined) {
65
72
  }
66
73
  }
67
74
  for (const dr of dirs) {
68
- const result = findAppDidFinishLaunchingWithOptions(dr);
69
- if (result)
75
+ const result = findAppDidFinishLaunchingWithOptionsInDirectory(dr);
76
+ if (result) {
77
+ (0, debug_1.debug)('Found AppDelegate in ' + dr);
70
78
  return result;
79
+ }
71
80
  }
72
81
  return null;
73
82
  }
74
- function addCodeSnippetToProject(projPath, files, dsn) {
75
- const appDelegate = findAppDidFinishLaunchingWithOptions(projPath, files);
83
+ function addCodeSnippetToProject(files, dsn) {
84
+ const appDelegate = findAppDidFinishLaunchingWithOptions(files);
76
85
  if (!appDelegate) {
77
86
  return false;
78
87
  }
@@ -129,6 +138,7 @@ exports.addCodeSnippetToProject = addCodeSnippetToProject;
129
138
  if (process.env.NODE_ENV === 'test') {
130
139
  exports.exportForTesting = {
131
140
  isAppDelegateFile,
141
+ findAppDidFinishLaunchingWithOptionsInDirectory,
132
142
  findAppDidFinishLaunchingWithOptions,
133
143
  };
134
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"code-tools.js","sourceRoot":"","sources":["../../../src/apple/code-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Sentry from '@sentry/node';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as templates from './templates';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n\nconst swiftAppLaunchRegex =\n /(func\\s+application\\s*\\(\\s*_\\s+application:\\s*[^,]+,\\s*didFinishLaunchingWithOptions[^,]+:\\s*[^)]+\\s*\\)\\s+->\\s+Bool\\s+{)|func\\s+applicationDidFinishLaunching\\s*\\(\\s*_\\s+aNotification:\\s+Notification\\s*\\)\\s*{/im;\nconst objcAppLaunchRegex =\n /-\\s*\\(\\s*BOOL\\s*\\)\\s*application:\\s*\\(\\s*UIApplication\\s*\\*\\s*\\)\\s*application\\s+didFinishLaunchingWithOptions:\\s*\\(\\s*NSDictionary\\s*\\*\\s*\\)\\s*launchOptions\\s*{/im;\nconst swiftUIRegex = /@main\\s+struct[^:]+:\\s*(SwiftUI\\.)?App\\s*{/im;\n\nfunction isAppDelegateFile(filePath: string): boolean {\n const appLaunchRegex = filePath.toLowerCase().endsWith('.swift')\n ? swiftAppLaunchRegex\n : objcAppLaunchRegex;\n\n const fileContent = fs.readFileSync(filePath, 'utf8');\n return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);\n}\n\nfunction findAppDidFinishLaunchingWithOptions(\n dir: string,\n files: string[] | undefined = undefined,\n): string | null {\n if (!files) {\n files = fs.readdirSync(dir);\n files = files.map((f) => path.join(dir, f));\n }\n\n //iterate over subdirectories later,\n //the appdelegate usually is in the top level\n const dirs: string[] = [];\n\n for (const filePath of files) {\n if (\n filePath.endsWith('.swift') ||\n filePath.endsWith('.m') ||\n filePath.endsWith('.mm')\n ) {\n if (fs.existsSync(filePath) && isAppDelegateFile(filePath)) {\n return filePath;\n }\n } else if (\n !path.basename(filePath).startsWith('.') &&\n !filePath.endsWith('.xcodeproj') &&\n !filePath.endsWith('.xcassets') &&\n fs.existsSync(filePath) &&\n fs.lstatSync(filePath).isDirectory()\n ) {\n dirs.push(filePath);\n }\n }\n\n for (const dr of dirs) {\n const result = findAppDidFinishLaunchingWithOptions(dr);\n if (result) return result;\n }\n return null;\n}\n\nexport function addCodeSnippetToProject(\n projPath: string,\n files: string[],\n dsn: string,\n): boolean {\n const appDelegate = findAppDidFinishLaunchingWithOptions(projPath, files);\n if (!appDelegate) {\n return false;\n }\n\n const fileContent = fs.readFileSync(appDelegate, 'utf8');\n const isSwift = appDelegate.toLowerCase().endsWith('.swift');\n const appLaunchRegex = isSwift ? swiftAppLaunchRegex : objcAppLaunchRegex;\n const importStatement = isSwift ? 'import Sentry\\n' : '@import Sentry;\\n';\n const checkForSentryInit = isSwift ? 'SentrySDK.start' : '[SentrySDK start';\n let codeSnippet = isSwift\n ? templates.getSwiftSnippet(dsn)\n : templates.getObjcSnippet(dsn);\n\n Sentry.setTag('code-language', isSwift ? 'swift' : 'objc');\n Sentry.setTag(\n 'ui-engine',\n swiftUIRegex.test(fileContent) ? 'swiftui' : 'uikit',\n );\n\n if (fileContent.includes(checkForSentryInit)) {\n //already initialized\n clack.log.info(\n 'Sentry is already initialized in your AppDelegate. Skipping adding the code snippet.',\n );\n return true;\n }\n\n let match = appLaunchRegex.exec(fileContent);\n if (!match) {\n const swiftUIMatch = swiftUIRegex.exec(fileContent);\n if (!swiftUIMatch) {\n // This branch is not reached, because we already checked for SwiftUI in isAppDelegateFile\n return false;\n }\n //Is SwiftUI with no init\n match = swiftUIMatch;\n codeSnippet = ` init() {\\n${codeSnippet} }`;\n }\n\n const insertIndex = match.index + match[0].length;\n let newFileContent =\n fileContent.slice(0, insertIndex) +\n '\\n' +\n codeSnippet +\n fileContent.slice(insertIndex);\n\n if (newFileContent.indexOf(importStatement) < 0) {\n const firstImport = /^[ \\t]*import +\\w+.*$/m.exec(newFileContent);\n if (firstImport) {\n const importIndex = firstImport.index + firstImport[0].length;\n newFileContent =\n newFileContent.slice(0, importIndex) +\n '\\n' +\n importStatement +\n newFileContent.slice(importIndex);\n } else {\n newFileContent = importStatement + newFileContent;\n }\n }\n\n fs.writeFileSync(appDelegate, newFileContent, 'utf8');\n\n clack.log.step('Added Sentry initialization code snippet to ' + appDelegate);\n return true;\n}\n\n/**\n * Exported for testing purposes, but should not be used in other modules.\n */\nexport let exportForTesting: {\n isAppDelegateFile: typeof isAppDelegateFile;\n findAppDidFinishLaunchingWithOptions: typeof findAppDidFinishLaunchingWithOptions;\n};\nif (process.env.NODE_ENV === 'test') {\n exportForTesting = {\n isAppDelegateFile,\n findAppDidFinishLaunchingWithOptions,\n };\n}\n"]}
1
+ {"version":3,"file":"code-tools.js","sourceRoot":"","sources":["../../../src/apple/code-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Sentry from '@sentry/node';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as templates from './templates';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport { debug } from '../utils/debug';\n\nconst swiftAppLaunchRegex =\n /(func\\s+application\\s*\\(\\s*_\\s+application:\\s*[^,]+,\\s*didFinishLaunchingWithOptions[^,]+:\\s*[^)]+\\s*\\)\\s+->\\s+Bool\\s+{)|func\\s+applicationDidFinishLaunching\\s*\\(\\s*_\\s+aNotification:\\s+Notification\\s*\\)\\s*{/im;\nconst objcAppLaunchRegex =\n /-\\s*\\(\\s*BOOL\\s*\\)\\s*application:\\s*\\(\\s*UIApplication\\s*\\*\\s*\\)\\s*application\\s+didFinishLaunchingWithOptions:\\s*\\(\\s*NSDictionary\\s*\\*\\s*\\)\\s*launchOptions\\s*{/im;\nconst swiftUIRegex = /@main\\s+struct[^:]+:\\s*(SwiftUI\\.)?App\\s*{/im;\n\nfunction isAppDelegateFile(filePath: string): boolean {\n debug('Checking if ' + filePath + ' is an AppDelegate file');\n const appLaunchRegex = filePath.toLowerCase().endsWith('.swift')\n ? swiftAppLaunchRegex\n : objcAppLaunchRegex;\n\n const fileContent = fs.readFileSync(filePath, 'utf8');\n return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);\n}\n\nfunction findAppDidFinishLaunchingWithOptionsInDirectory(\n dir: string,\n): string | null {\n debug('Searching for AppDelegate in directory: ' + dir);\n const files = fs.readdirSync(dir);\n const filePaths = files.map((f) => path.join(dir, f));\n return findAppDidFinishLaunchingWithOptions(filePaths);\n}\n\nfunction findAppDidFinishLaunchingWithOptions(files: string[]): string | null {\n debug(`Searching for AppDelegate in ${files.length} files`);\n\n // Iterate over subdirectories after iterating over files,\n // because the AppDelegate is usually in the top level\n const dirs: string[] = [];\n for (const filePath of files) {\n debug('Checking file: ' + filePath);\n if (\n filePath.endsWith('.swift') ||\n filePath.endsWith('.m') ||\n filePath.endsWith('.mm')\n ) {\n if (fs.existsSync(filePath) && isAppDelegateFile(filePath)) {\n debug('Found AppDelegate in ' + filePath);\n return filePath;\n }\n } else if (\n !path.basename(filePath).startsWith('.') &&\n !filePath.endsWith('.xcodeproj') &&\n !filePath.endsWith('.xcassets') &&\n fs.existsSync(filePath) &&\n fs.lstatSync(filePath).isDirectory()\n ) {\n dirs.push(filePath);\n }\n }\n\n for (const dr of dirs) {\n const result = findAppDidFinishLaunchingWithOptionsInDirectory(dr);\n if (result) {\n debug('Found AppDelegate in ' + dr);\n return result;\n }\n }\n return null;\n}\n\nexport function addCodeSnippetToProject(files: string[], dsn: string): boolean {\n const appDelegate = findAppDidFinishLaunchingWithOptions(files);\n if (!appDelegate) {\n return false;\n }\n\n const fileContent = fs.readFileSync(appDelegate, 'utf8');\n const isSwift = appDelegate.toLowerCase().endsWith('.swift');\n const appLaunchRegex = isSwift ? swiftAppLaunchRegex : objcAppLaunchRegex;\n const importStatement = isSwift ? 'import Sentry\\n' : '@import Sentry;\\n';\n const checkForSentryInit = isSwift ? 'SentrySDK.start' : '[SentrySDK start';\n let codeSnippet = isSwift\n ? templates.getSwiftSnippet(dsn)\n : templates.getObjcSnippet(dsn);\n\n Sentry.setTag('code-language', isSwift ? 'swift' : 'objc');\n Sentry.setTag(\n 'ui-engine',\n swiftUIRegex.test(fileContent) ? 'swiftui' : 'uikit',\n );\n\n if (fileContent.includes(checkForSentryInit)) {\n //already initialized\n clack.log.info(\n 'Sentry is already initialized in your AppDelegate. Skipping adding the code snippet.',\n );\n return true;\n }\n\n let match = appLaunchRegex.exec(fileContent);\n if (!match) {\n const swiftUIMatch = swiftUIRegex.exec(fileContent);\n if (!swiftUIMatch) {\n // This branch is not reached, because we already checked for SwiftUI in isAppDelegateFile\n return false;\n }\n //Is SwiftUI with no init\n match = swiftUIMatch;\n codeSnippet = ` init() {\\n${codeSnippet} }`;\n }\n\n const insertIndex = match.index + match[0].length;\n let newFileContent =\n fileContent.slice(0, insertIndex) +\n '\\n' +\n codeSnippet +\n fileContent.slice(insertIndex);\n\n if (newFileContent.indexOf(importStatement) < 0) {\n const firstImport = /^[ \\t]*import +\\w+.*$/m.exec(newFileContent);\n if (firstImport) {\n const importIndex = firstImport.index + firstImport[0].length;\n newFileContent =\n newFileContent.slice(0, importIndex) +\n '\\n' +\n importStatement +\n newFileContent.slice(importIndex);\n } else {\n newFileContent = importStatement + newFileContent;\n }\n }\n\n fs.writeFileSync(appDelegate, newFileContent, 'utf8');\n\n clack.log.step('Added Sentry initialization code snippet to ' + appDelegate);\n return true;\n}\n\n/**\n * Exported for testing purposes, but should not be used in other modules.\n */\nexport let exportForTesting: {\n isAppDelegateFile: typeof isAppDelegateFile;\n findAppDidFinishLaunchingWithOptionsInDirectory: typeof findAppDidFinishLaunchingWithOptionsInDirectory;\n findAppDidFinishLaunchingWithOptions: typeof findAppDidFinishLaunchingWithOptions;\n};\nif (process.env.NODE_ENV === 'test') {\n exportForTesting = {\n isAppDelegateFile,\n findAppDidFinishLaunchingWithOptionsInDirectory,\n findAppDidFinishLaunchingWithOptions,\n };\n}\n"]}
@@ -35,14 +35,16 @@ const telemetry_1 = require("../telemetry");
35
35
  const debug_1 = require("../utils/debug");
36
36
  const codeTools = __importStar(require("./code-tools"));
37
37
  function injectCodeSnippet({ project, target, dsn, }) {
38
- (0, debug_1.debug)(`Injecting code snippet into project at path: ${chalk_1.default.cyan(project.projectPath)}`);
38
+ (0, debug_1.debug)(`Injecting code snippet into project at path: ${chalk_1.default.cyan(project.baseDir)}`);
39
39
  const codeAdded = (0, telemetry_1.traceStep)('Add code snippet', () => {
40
- const files = project.filesForTarget(target);
40
+ const files = project.getSourceFilesForTarget(target);
41
41
  if (files === undefined || files.length == 0) {
42
+ (0, debug_1.debug)('No files found for target: ' + target);
42
43
  Sentry.setTag('snippet-candidate-files-not-found', true);
43
44
  return false;
44
45
  }
45
- return codeTools.addCodeSnippetToProject(project.projectPath, files, dsn);
46
+ (0, debug_1.debug)(`Adding code snippet to ${files.length} candidate files`);
47
+ return codeTools.addCodeSnippetToProject(files, dsn);
46
48
  });
47
49
  Sentry.setTag('Snippet-Added', codeAdded);
48
50
  (0, debug_1.debug)(`Snippet added: ${chalk_1.default.cyan(codeAdded.toString())}`);
@@ -1 +1 @@
1
- {"version":3,"file":"inject-code-snippet.js","sourceRoot":"","sources":["../../../src/apple/inject-code-snippet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+EAA+E;AAC/E,6DAAmC;AACnC,qDAAuC;AACvC,kDAA0B;AAC1B,4CAAyC;AACzC,0CAAuC;AACvC,wDAA0C;AAG1C,SAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,MAAM,EACN,GAAG,GAKJ;IACC,IAAA,aAAK,EACH,gDAAgD,eAAK,CAAC,IAAI,CACxD,OAAO,CAAC,WAAW,CACpB,EAAE,CACJ,CAAC;IACF,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,kBAAkB,EAAE,GAAG,EAAE;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE;YAC5C,MAAM,CAAC,MAAM,CAAC,mCAAmC,EAAE,IAAI,CAAC,CAAC;YACzD,OAAO,KAAK,CAAC;SACd;QAED,OAAO,SAAS,CAAC,uBAAuB,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAC1C,IAAA,aAAK,EAAC,kBAAkB,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAE5D,IAAI,CAAC,SAAS,EAAE;QACd,iBAAK,CAAC,GAAG,CAAC,IAAI,CACZ,iNAAiN,CAClN,CAAC;KACH;AACH,CAAC;AA/BD,8CA+BC","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport * as Sentry from '@sentry/node';\nimport chalk from 'chalk';\nimport { traceStep } from '../telemetry';\nimport { debug } from '../utils/debug';\nimport * as codeTools from './code-tools';\nimport { XcodeProject } from './xcode-manager';\n\nexport function injectCodeSnippet({\n project,\n target,\n dsn,\n}: {\n project: XcodeProject;\n target: string;\n dsn: string;\n}) {\n debug(\n `Injecting code snippet into project at path: ${chalk.cyan(\n project.projectPath,\n )}`,\n );\n const codeAdded = traceStep('Add code snippet', () => {\n const files = project.filesForTarget(target);\n if (files === undefined || files.length == 0) {\n Sentry.setTag('snippet-candidate-files-not-found', true);\n return false;\n }\n\n return codeTools.addCodeSnippetToProject(project.projectPath, files, dsn);\n });\n Sentry.setTag('Snippet-Added', codeAdded);\n debug(`Snippet added: ${chalk.cyan(codeAdded.toString())}`);\n\n if (!codeAdded) {\n clack.log.warn(\n 'Added the Sentry dependency to your project but could not add the Sentry code snippet. Please add the code snippet manually by following the docs: https://docs.sentry.io/platforms/apple/guides/ios/#configure',\n );\n }\n}\n"]}
1
+ {"version":3,"file":"inject-code-snippet.js","sourceRoot":"","sources":["../../../src/apple/inject-code-snippet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+EAA+E;AAC/E,6DAAmC;AACnC,qDAAuC;AACvC,kDAA0B;AAC1B,4CAAyC;AACzC,0CAAuC;AACvC,wDAA0C;AAG1C,SAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,MAAM,EACN,GAAG,GAKJ;IACC,IAAA,aAAK,EACH,gDAAgD,eAAK,CAAC,IAAI,CACxD,OAAO,CAAC,OAAO,CAChB,EAAE,CACJ,CAAC;IACF,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,kBAAkB,EAAE,GAAG,EAAE;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE;YAC5C,IAAA,aAAK,EAAC,6BAA6B,GAAG,MAAM,CAAC,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,mCAAmC,EAAE,IAAI,CAAC,CAAC;YACzD,OAAO,KAAK,CAAC;SACd;QAED,IAAA,aAAK,EAAC,0BAA0B,KAAK,CAAC,MAAM,kBAAkB,CAAC,CAAC;QAChE,OAAO,SAAS,CAAC,uBAAuB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAC1C,IAAA,aAAK,EAAC,kBAAkB,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAE5D,IAAI,CAAC,SAAS,EAAE;QACd,iBAAK,CAAC,GAAG,CAAC,IAAI,CACZ,iNAAiN,CAClN,CAAC;KACH;AACH,CAAC;AAjCD,8CAiCC","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport * as Sentry from '@sentry/node';\nimport chalk from 'chalk';\nimport { traceStep } from '../telemetry';\nimport { debug } from '../utils/debug';\nimport * as codeTools from './code-tools';\nimport { XcodeProject } from './xcode-manager';\n\nexport function injectCodeSnippet({\n project,\n target,\n dsn,\n}: {\n project: XcodeProject;\n target: string;\n dsn: string;\n}) {\n debug(\n `Injecting code snippet into project at path: ${chalk.cyan(\n project.baseDir,\n )}`,\n );\n const codeAdded = traceStep('Add code snippet', () => {\n const files = project.getSourceFilesForTarget(target);\n if (files === undefined || files.length == 0) {\n debug('No files found for target: ' + target);\n Sentry.setTag('snippet-candidate-files-not-found', true);\n return false;\n }\n\n debug(`Adding code snippet to ${files.length} candidate files`);\n return codeTools.addCodeSnippetToProject(files, dsn);\n });\n Sentry.setTag('Snippet-Added', codeAdded);\n debug(`Snippet added: ${chalk.cyan(codeAdded.toString())}`);\n\n if (!codeAdded) {\n clack.log.warn(\n 'Added the Sentry dependency to your project but could not add the Sentry code snippet. Please add the code snippet manually by following the docs: https://docs.sentry.io/platforms/apple/guides/ios/#configure',\n );\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export declare class MacOSSystemHelpers {
2
+ static findSDKRootDirectoryPath(): string | undefined;
3
+ static findDeveloperDirectoryPath(): string | undefined;
4
+ static readXcodeBuildSettings(projectPath: string): Record<string, string> | undefined;
5
+ }