@sentry/wizard 4.5.0 → 4.7.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 (293) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/README.md +23 -19
  3. package/dist/bin.js +22 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/e2e-tests/tests/flutter.test.js +16 -16
  6. package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
  7. package/dist/e2e-tests/tests/help-message.test.js +56 -0
  8. package/dist/e2e-tests/tests/help-message.test.js.map +1 -0
  9. package/dist/e2e-tests/tests/nextjs-14.test.js +17 -16
  10. package/dist/e2e-tests/tests/nextjs-14.test.js.map +1 -1
  11. package/dist/e2e-tests/tests/nextjs-15.test.js +16 -16
  12. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  13. package/dist/e2e-tests/tests/nuxt-3.test.js +13 -12
  14. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  15. package/dist/e2e-tests/tests/nuxt-4.test.js +13 -12
  16. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  17. package/dist/e2e-tests/tests/remix.test.js +20 -20
  18. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  19. package/dist/e2e-tests/tests/sveltekit.test.js +20 -20
  20. package/dist/e2e-tests/tests/sveltekit.test.js.map +1 -1
  21. package/dist/e2e-tests/utils/index.d.ts +1 -1
  22. package/dist/e2e-tests/utils/index.js +35 -13
  23. package/dist/e2e-tests/utils/index.js.map +1 -1
  24. package/dist/lib/Constants.d.ts +7 -1
  25. package/dist/lib/Constants.js.map +1 -1
  26. package/dist/lib/Helper/File.d.ts +1 -1
  27. package/dist/lib/Helper/File.js +1 -3
  28. package/dist/lib/Helper/File.js.map +1 -1
  29. package/dist/lib/Helper/Logging.d.ts +4 -1
  30. package/dist/lib/Helper/Logging.js +3 -0
  31. package/dist/lib/Helper/Logging.js.map +1 -1
  32. package/dist/lib/Helper/Package.d.ts +5 -3
  33. package/dist/lib/Helper/Package.js +2 -2
  34. package/dist/lib/Helper/Package.js.map +1 -1
  35. package/dist/lib/Helper/SentryCli.d.ts +20 -7
  36. package/dist/lib/Helper/SentryCli.js +21 -13
  37. package/dist/lib/Helper/SentryCli.js.map +1 -1
  38. package/dist/lib/Helper/Wizard.js +9 -5
  39. package/dist/lib/Helper/Wizard.js.map +1 -1
  40. package/dist/lib/Helper/__tests__/File.js +9 -9
  41. package/dist/lib/Helper/__tests__/File.js.map +1 -1
  42. package/dist/lib/Helper/__tests__/MergeConfig.js +17 -17
  43. package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
  44. package/dist/lib/Helper/__tests__/SentryCli.js +39 -21
  45. package/dist/lib/Helper/__tests__/SentryCli.js.map +1 -1
  46. package/dist/lib/Setup.d.ts +4 -1
  47. package/dist/lib/Setup.js +12 -2
  48. package/dist/lib/Setup.js.map +1 -1
  49. package/dist/lib/Steps/BaseStep.d.ts +1 -1
  50. package/dist/lib/Steps/BaseStep.js.map +1 -1
  51. package/dist/lib/Steps/Integrations/BaseIntegration.js +1 -2
  52. package/dist/lib/Steps/Integrations/BaseIntegration.js.map +1 -1
  53. package/dist/lib/Steps/Integrations/Cordova.js +14 -10
  54. package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
  55. package/dist/lib/Steps/Integrations/Electron.d.ts +4 -1
  56. package/dist/lib/Steps/Integrations/Electron.js +1 -1
  57. package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
  58. package/dist/lib/Steps/Integrations/MobileProject.d.ts +3 -1
  59. package/dist/lib/Steps/Integrations/MobileProject.js +1 -1
  60. package/dist/lib/Steps/Integrations/MobileProject.js.map +1 -1
  61. package/dist/lib/Steps/PromptForParameters.d.ts +4 -1
  62. package/dist/lib/Steps/PromptForParameters.js.map +1 -1
  63. package/dist/lib/Steps/SentryProjectSelector.d.ts +42 -1
  64. package/dist/lib/Steps/SentryProjectSelector.js +1 -1
  65. package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
  66. package/dist/lib/Steps/WaitForSentry.d.ts +3 -1
  67. package/dist/lib/Steps/WaitForSentry.js +4 -4
  68. package/dist/lib/Steps/WaitForSentry.js.map +1 -1
  69. package/dist/lib/Steps/Welcome.js +5 -0
  70. package/dist/lib/Steps/Welcome.js.map +1 -1
  71. package/dist/lib/Types.d.ts +14 -0
  72. package/dist/lib/Types.js +3 -0
  73. package/dist/lib/Types.js.map +1 -0
  74. package/dist/lib/__tests__/Env.js +10 -16
  75. package/dist/lib/__tests__/Env.js.map +1 -1
  76. package/dist/src/android/android-wizard.js +15 -12
  77. package/dist/src/android/android-wizard.js.map +1 -1
  78. package/dist/src/android/code-tools.js +1 -1
  79. package/dist/src/android/code-tools.js.map +1 -1
  80. package/dist/src/android/gradle.js +4 -4
  81. package/dist/src/android/gradle.js.map +1 -1
  82. package/dist/src/android/manifest.js +1 -1
  83. package/dist/src/android/manifest.js.map +1 -1
  84. package/dist/src/apple/apple-wizard.d.ts +2 -2
  85. package/dist/src/apple/apple-wizard.js +54 -175
  86. package/dist/src/apple/apple-wizard.js.map +1 -1
  87. package/dist/src/apple/check-installed-cli.d.ts +1 -0
  88. package/dist/src/apple/check-installed-cli.js +60 -0
  89. package/dist/src/apple/check-installed-cli.js.map +1 -0
  90. package/dist/src/apple/cocoapod.js +1 -1
  91. package/dist/src/apple/cocoapod.js.map +1 -1
  92. package/dist/src/apple/code-tools.js +1 -1
  93. package/dist/src/apple/code-tools.js.map +1 -1
  94. package/dist/src/apple/configure-fastlane.d.ts +5 -0
  95. package/dist/src/apple/configure-fastlane.js +66 -0
  96. package/dist/src/apple/configure-fastlane.js.map +1 -0
  97. package/dist/src/apple/configure-package-manager.d.ts +5 -0
  98. package/dist/src/apple/configure-package-manager.js +68 -0
  99. package/dist/src/apple/configure-package-manager.js.map +1 -0
  100. package/dist/src/apple/configure-sentry-cli.d.ts +4 -0
  101. package/dist/src/apple/configure-sentry-cli.js +47 -0
  102. package/dist/src/apple/configure-sentry-cli.js.map +1 -0
  103. package/dist/src/apple/configure-xcode-project.d.ts +8 -0
  104. package/dist/src/apple/configure-xcode-project.js +11 -0
  105. package/dist/src/apple/configure-xcode-project.js.map +1 -0
  106. package/dist/src/apple/fastlane.d.ts +1 -1
  107. package/dist/src/apple/fastlane.js +5 -5
  108. package/dist/src/apple/fastlane.js.map +1 -1
  109. package/dist/src/apple/inject-code-snippet.d.ts +6 -0
  110. package/dist/src/apple/inject-code-snippet.js +54 -0
  111. package/dist/src/apple/inject-code-snippet.js.map +1 -0
  112. package/dist/src/apple/lookup-xcode-project.d.ts +7 -0
  113. package/dist/src/apple/lookup-xcode-project.js +98 -0
  114. package/dist/src/apple/lookup-xcode-project.js.map +1 -0
  115. package/dist/src/apple/options.d.ts +4 -0
  116. package/dist/src/apple/options.js +3 -0
  117. package/dist/src/apple/options.js.map +1 -0
  118. package/dist/src/apple/search-xcode-project-at-path.d.ts +1 -0
  119. package/dist/src/apple/search-xcode-project-at-path.js +70 -0
  120. package/dist/src/apple/search-xcode-project-at-path.js.map +1 -0
  121. package/dist/src/apple/templates.js +11 -7
  122. package/dist/src/apple/templates.js.map +1 -1
  123. package/dist/src/apple/xcode-manager.js +4 -7
  124. package/dist/src/apple/xcode-manager.js.map +1 -1
  125. package/dist/src/flutter/code-tools.js +3 -3
  126. package/dist/src/flutter/code-tools.js.map +1 -1
  127. package/dist/src/flutter/flutter-wizard.js +21 -15
  128. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  129. package/dist/src/flutter/templates.js +4 -4
  130. package/dist/src/flutter/templates.js.map +1 -1
  131. package/dist/src/nextjs/nextjs-wizard.js +118 -43
  132. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  133. package/dist/src/nextjs/templates.d.ts +10 -1
  134. package/dist/src/nextjs/templates.js +192 -62
  135. package/dist/src/nextjs/templates.js.map +1 -1
  136. package/dist/src/nuxt/nuxt-wizard.js +21 -16
  137. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  138. package/dist/src/nuxt/sdk-example.js +3 -3
  139. package/dist/src/nuxt/sdk-example.js.map +1 -1
  140. package/dist/src/nuxt/sdk-setup.js +9 -9
  141. package/dist/src/nuxt/sdk-setup.js.map +1 -1
  142. package/dist/src/nuxt/templates.js +173 -58
  143. package/dist/src/nuxt/templates.js.map +1 -1
  144. package/dist/src/nuxt/utils.js +6 -3
  145. package/dist/src/nuxt/utils.js.map +1 -1
  146. package/dist/src/react-native/expo-env-file.js +1 -1
  147. package/dist/src/react-native/expo-env-file.js.map +1 -1
  148. package/dist/src/react-native/expo-metro.js +4 -4
  149. package/dist/src/react-native/expo-metro.js.map +1 -1
  150. package/dist/src/react-native/expo.js +4 -4
  151. package/dist/src/react-native/expo.js.map +1 -1
  152. package/dist/src/react-native/javascript.d.ts +6 -4
  153. package/dist/src/react-native/javascript.js +31 -15
  154. package/dist/src/react-native/javascript.js.map +1 -1
  155. package/dist/src/react-native/metro.js +8 -8
  156. package/dist/src/react-native/metro.js.map +1 -1
  157. package/dist/src/react-native/react-native-wizard.d.ts +5 -1
  158. package/dist/src/react-native/react-native-wizard.js +66 -36
  159. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  160. package/dist/src/react-native/uninstall.js +8 -5
  161. package/dist/src/react-native/uninstall.js.map +1 -1
  162. package/dist/src/react-native/xcode.d.ts +9 -4
  163. package/dist/src/react-native/xcode.js +65 -22
  164. package/dist/src/react-native/xcode.js.map +1 -1
  165. package/dist/src/remix/codemods/handle-error.js +4 -1
  166. package/dist/src/remix/codemods/handle-error.js.map +1 -1
  167. package/dist/src/remix/remix-wizard.js +23 -18
  168. package/dist/src/remix/remix-wizard.js.map +1 -1
  169. package/dist/src/remix/sdk-example.js +163 -64
  170. package/dist/src/remix/sdk-example.js.map +1 -1
  171. package/dist/src/remix/sdk-setup.js +11 -7
  172. package/dist/src/remix/sdk-setup.js.map +1 -1
  173. package/dist/src/run.d.ts +3 -1
  174. package/dist/src/run.js +29 -9
  175. package/dist/src/run.js.map +1 -1
  176. package/dist/src/sourcemaps/sourcemaps-wizard.js +30 -28
  177. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  178. package/dist/src/sourcemaps/tools/angular.js +3 -3
  179. package/dist/src/sourcemaps/tools/angular.js.map +1 -1
  180. package/dist/src/sourcemaps/tools/create-react-app.js +3 -3
  181. package/dist/src/sourcemaps/tools/create-react-app.js.map +1 -1
  182. package/dist/src/sourcemaps/tools/esbuild.js +6 -6
  183. package/dist/src/sourcemaps/tools/esbuild.js.map +1 -1
  184. package/dist/src/sourcemaps/tools/nextjs.js +5 -5
  185. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
  186. package/dist/src/sourcemaps/tools/remix.js +4 -4
  187. package/dist/src/sourcemaps/tools/remix.js.map +1 -1
  188. package/dist/src/sourcemaps/tools/rollup.js +6 -6
  189. package/dist/src/sourcemaps/tools/rollup.js.map +1 -1
  190. package/dist/src/sourcemaps/tools/sentry-cli.js +15 -15
  191. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  192. package/dist/src/sourcemaps/tools/tsc.js +6 -6
  193. package/dist/src/sourcemaps/tools/tsc.js.map +1 -1
  194. package/dist/src/sourcemaps/tools/vite.js +12 -12
  195. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  196. package/dist/src/sourcemaps/tools/webpack.js +10 -10
  197. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  198. package/dist/src/sourcemaps/utils/detect-tool.js +2 -2
  199. package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
  200. package/dist/src/sourcemaps/utils/other-wizards.js +5 -5
  201. package/dist/src/sourcemaps/utils/other-wizards.js.map +1 -1
  202. package/dist/src/sourcemaps/utils/sdk-version.js +7 -7
  203. package/dist/src/sourcemaps/utils/sdk-version.js.map +1 -1
  204. package/dist/src/sveltekit/sdk-example.js +1 -1
  205. package/dist/src/sveltekit/sdk-example.js.map +1 -1
  206. package/dist/src/sveltekit/sdk-setup.js +15 -14
  207. package/dist/src/sveltekit/sdk-setup.js.map +1 -1
  208. package/dist/src/sveltekit/sveltekit-wizard.js +25 -20
  209. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  210. package/dist/src/sveltekit/templates.js +126 -37
  211. package/dist/src/sveltekit/templates.js.map +1 -1
  212. package/dist/src/telemetry.js +11 -0
  213. package/dist/src/telemetry.js.map +1 -1
  214. package/dist/src/utils/{clack-utils.d.ts → clack/index.d.ts} +45 -7
  215. package/dist/src/utils/{clack-utils.js → clack/index.js} +75 -20
  216. package/dist/src/utils/clack/index.js.map +1 -0
  217. package/dist/src/utils/debug.js +1 -1
  218. package/dist/src/utils/debug.js.map +1 -1
  219. package/dist/src/utils/find-files-with-extension.d.ts +1 -0
  220. package/dist/src/utils/find-files-with-extension.js +39 -0
  221. package/dist/src/utils/find-files-with-extension.js.map +1 -0
  222. package/dist/src/utils/package-manager.d.ts +8 -1
  223. package/dist/src/utils/package-manager.js +79 -23
  224. package/dist/src/utils/package-manager.js.map +1 -1
  225. package/dist/src/utils/sentrycli-utils.js +0 -1
  226. package/dist/src/utils/sentrycli-utils.js.map +1 -1
  227. package/dist/src/utils/types.d.ts +4 -0
  228. package/dist/src/utils/types.js.map +1 -1
  229. package/dist/src/version.d.ts +1 -1
  230. package/dist/src/version.js +1 -1
  231. package/dist/src/version.js.map +1 -1
  232. package/dist/test/android/code-tools.test.js +13 -13
  233. package/dist/test/android/code-tools.test.js.map +1 -1
  234. package/dist/test/apple/cocoapod.test.js +78 -73
  235. package/dist/test/apple/cocoapod.test.js.map +1 -1
  236. package/dist/test/apple/code-tools.test.js +174 -167
  237. package/dist/test/apple/code-tools.test.js.map +1 -1
  238. package/dist/test/apple/fastfile.test.js +87 -84
  239. package/dist/test/apple/fastfile.test.js.map +1 -1
  240. package/dist/test/apple/templates.test.js +32 -27
  241. package/dist/test/apple/templates.test.js.map +1 -1
  242. package/dist/test/apple/xcode-manager.test.js +208 -185
  243. package/dist/test/apple/xcode-manager.test.js.map +1 -1
  244. package/dist/test/flutter/code-tools.test.js +29 -30
  245. package/dist/test/flutter/code-tools.test.js.map +1 -1
  246. package/dist/test/flutter/templates.test.js +38 -37
  247. package/dist/test/flutter/templates.test.js.map +1 -1
  248. package/dist/test/nextjs/templates.test.js +155 -103
  249. package/dist/test/nextjs/templates.test.js.map +1 -1
  250. package/dist/test/nuxt/templates.test.js +25 -24
  251. package/dist/test/nuxt/templates.test.js.map +1 -1
  252. package/dist/test/react-native/expo-metro.test.js +12 -11
  253. package/dist/test/react-native/expo-metro.test.js.map +1 -1
  254. package/dist/test/react-native/expo.test.js +11 -10
  255. package/dist/test/react-native/expo.test.js.map +1 -1
  256. package/dist/test/react-native/gradle.test.js +27 -26
  257. package/dist/test/react-native/gradle.test.js.map +1 -1
  258. package/dist/test/react-native/javascript.test.js +109 -59
  259. package/dist/test/react-native/javascript.test.js.map +1 -1
  260. package/dist/test/react-native/metro.test.js +66 -65
  261. package/dist/test/react-native/metro.test.js.map +1 -1
  262. package/dist/test/react-native/xcode.test.js +138 -37
  263. package/dist/test/react-native/xcode.test.js.map +1 -1
  264. package/dist/test/remix/client-entry.test.js +8 -7
  265. package/dist/test/remix/client-entry.test.js.map +1 -1
  266. package/dist/test/remix/server-instrumentation.test.js +6 -5
  267. package/dist/test/remix/server-instrumentation.test.js.map +1 -1
  268. package/dist/test/sourcemaps/tools/sentry-cli.test.js +21 -21
  269. package/dist/test/sourcemaps/tools/sentry-cli.test.js.map +1 -1
  270. package/dist/test/sourcemaps/tools/tsc.test.js +13 -14
  271. package/dist/test/sourcemaps/tools/tsc.test.js.map +1 -1
  272. package/dist/test/sourcemaps/tools/vite.test.js +13 -14
  273. package/dist/test/sourcemaps/tools/vite.test.js.map +1 -1
  274. package/dist/test/sourcemaps/tools/webpack.test.js +19 -20
  275. package/dist/test/sourcemaps/tools/webpack.test.js.map +1 -1
  276. package/dist/test/sveltekit/templates.test.js +13 -12
  277. package/dist/test/sveltekit/templates.test.js.map +1 -1
  278. package/dist/test/utils/ast-utils.test.js +45 -44
  279. package/dist/test/utils/ast-utils.test.js.map +1 -1
  280. package/dist/test/utils/clack/index.test.d.ts +1 -0
  281. package/dist/test/utils/clack/index.test.js +375 -0
  282. package/dist/test/utils/clack/index.test.js.map +1 -0
  283. package/dist/test/utils/package-manager.test.d.ts +1 -0
  284. package/dist/test/utils/package-manager.test.js +30 -0
  285. package/dist/test/utils/package-manager.test.js.map +1 -0
  286. package/package.json +10 -38
  287. package/dist/e2e-tests/jest.config.d.ts +0 -17
  288. package/dist/e2e-tests/jest.config.js +0 -23
  289. package/dist/e2e-tests/jest.config.js.map +0 -1
  290. package/dist/src/utils/clack-utils.js.map +0 -1
  291. package/dist/test/utils/clack-utils.test.js +0 -306
  292. package/dist/test/utils/clack-utils.test.js.map +0 -1
  293. /package/dist/{test/utils/clack-utils.test.d.ts → e2e-tests/tests/help-message.test.d.ts} +0 -0
@@ -29,18 +29,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.runAndroidWizard = void 0;
30
30
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
31
31
  const fs = __importStar(require("fs"));
32
- // @ts-ignore - clack is ESM and TS complains about that. It works though
32
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
33
33
  const clack = __importStar(require("@clack/prompts"));
34
- const path = __importStar(require("path"));
35
34
  const Sentry = __importStar(require("@sentry/node"));
35
+ const chalk_1 = __importDefault(require("chalk"));
36
+ const path = __importStar(require("path"));
37
+ const telemetry_1 = require("../telemetry");
38
+ const clack_1 = require("../utils/clack");
39
+ const codetools = __importStar(require("./code-tools"));
36
40
  const gradle = __importStar(require("./gradle"));
37
41
  const manifest = __importStar(require("./manifest"));
38
- const codetools = __importStar(require("./code-tools"));
39
- const clack_utils_1 = require("../utils/clack-utils");
40
- const telemetry_1 = require("../telemetry");
41
- const chalk_1 = __importDefault(require("chalk"));
42
42
  const proguardMappingCliSetupConfig = {
43
- ...clack_utils_1.propertiesCliSetupConfig,
43
+ ...clack_1.propertiesCliSetupConfig,
44
44
  name: 'proguard mappings',
45
45
  };
46
46
  async function runAndroidWizard(options) {
@@ -52,11 +52,14 @@ async function runAndroidWizard(options) {
52
52
  }
53
53
  exports.runAndroidWizard = runAndroidWizard;
54
54
  async function runAndroidWizardWithTelemetry(options) {
55
- (0, clack_utils_1.printWelcome)({
55
+ (0, clack_1.printWelcome)({
56
56
  wizardName: 'Sentry Android Wizard',
57
57
  promoCode: options.promoCode,
58
58
  });
59
- await (0, clack_utils_1.confirmContinueIfNoOrDirtyGitRepo)();
59
+ await (0, clack_1.confirmContinueIfNoOrDirtyGitRepo)({
60
+ ignoreGitChanges: options.ignoreGitChanges,
61
+ cwd: undefined,
62
+ });
60
63
  const projectDir = process.cwd();
61
64
  const buildGradleFiles = findFilesWithExtensions(projectDir, [
62
65
  '.gradle',
@@ -65,11 +68,11 @@ async function runAndroidWizardWithTelemetry(options) {
65
68
  if (!buildGradleFiles || buildGradleFiles.length === 0) {
66
69
  clack.log.error('No Gradle project found. Please run this command from the root of your project.');
67
70
  Sentry.captureException('No Gradle project found');
68
- await (0, clack_utils_1.abort)();
71
+ await (0, clack_1.abort)();
69
72
  return;
70
73
  }
71
74
  const appFile = await (0, telemetry_1.traceStep)('Select App File', () => gradle.selectAppFile(buildGradleFiles));
72
- const { selectedProject, selfHosted, sentryUrl, authToken } = await (0, clack_utils_1.getOrAskForProjectData)(options, 'android');
75
+ const { selectedProject, selfHosted, sentryUrl, authToken } = await (0, clack_1.getOrAskForProjectData)(options, 'android');
73
76
  // ======== STEP 1. Add Sentry Gradle Plugin to build.gradle(.kts) ============
74
77
  clack.log.step(`Adding ${chalk_1.default.bold('Sentry Gradle plugin')} to your app's ${chalk_1.default.cyan('build.gradle')} file.`);
75
78
  const pluginAdded = await (0, telemetry_1.traceStep)('Add Gradle Plugin', () => gradle.addGradlePlugin(appFile, selectedProject.organization.slug, selectedProject.slug));
@@ -112,7 +115,7 @@ async function runAndroidWizardWithTelemetry(options) {
112
115
  }
113
116
  // ======== STEP 4. Add sentry-cli config file ============
114
117
  clack.log.step(`Configuring ${chalk_1.default.bold('proguard mappings upload')} via the ${chalk_1.default.cyan('sentry.properties')} file.`);
115
- await (0, clack_utils_1.addSentryCliConfig)({ authToken }, proguardMappingCliSetupConfig);
118
+ await (0, clack_1.addSentryCliConfig)({ authToken }, proguardMappingCliSetupConfig);
116
119
  // ======== OUTRO ========
117
120
  const issuesPageLink = selfHosted
118
121
  ? `${sentryUrl}organizations/${selectedProject.organization.slug}/issues/?project=${selectedProject.id}`
@@ -1 +1 @@
1
- {"version":3,"file":"android-wizard.js","sourceRoot":"","sources":["../../../src/android/android-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport * as fs from 'fs';\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport * as path from 'path';\nimport * as Sentry from '@sentry/node';\nimport * as gradle from './gradle';\nimport * as manifest from './manifest';\nimport * as codetools from './code-tools';\nimport {\n CliSetupConfig,\n abort,\n addSentryCliConfig,\n confirmContinueIfNoOrDirtyGitRepo,\n getOrAskForProjectData,\n printWelcome,\n propertiesCliSetupConfig,\n} from '../utils/clack-utils';\nimport { WizardOptions } from '../utils/types';\nimport { traceStep, withTelemetry } from '../telemetry';\nimport chalk from 'chalk';\n\nconst proguardMappingCliSetupConfig: CliSetupConfig = {\n ...propertiesCliSetupConfig,\n name: 'proguard mappings',\n};\n\nexport async function runAndroidWizard(options: WizardOptions): Promise<void> {\n return withTelemetry(\n {\n enabled: options.telemetryEnabled,\n integration: 'android',\n wizardOptions: options,\n },\n () => runAndroidWizardWithTelemetry(options),\n );\n}\n\nasync function runAndroidWizardWithTelemetry(\n options: WizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry Android Wizard',\n promoCode: options.promoCode,\n });\n\n await confirmContinueIfNoOrDirtyGitRepo();\n\n const projectDir = process.cwd();\n const buildGradleFiles = findFilesWithExtensions(projectDir, [\n '.gradle',\n 'gradle.kts',\n ]);\n\n if (!buildGradleFiles || buildGradleFiles.length === 0) {\n clack.log.error(\n 'No Gradle project found. Please run this command from the root of your project.',\n );\n Sentry.captureException('No Gradle project found');\n await abort();\n return;\n }\n\n const appFile = await traceStep('Select App File', () =>\n gradle.selectAppFile(buildGradleFiles),\n );\n\n const { selectedProject, selfHosted, sentryUrl, authToken } =\n await getOrAskForProjectData(options, 'android');\n\n // ======== STEP 1. Add Sentry Gradle Plugin to build.gradle(.kts) ============\n clack.log.step(\n `Adding ${chalk.bold('Sentry Gradle plugin')} to your app's ${chalk.cyan(\n 'build.gradle',\n )} file.`,\n );\n const pluginAdded = await traceStep('Add Gradle Plugin', () =>\n gradle.addGradlePlugin(\n appFile,\n selectedProject.organization.slug,\n selectedProject.slug,\n ),\n );\n if (!pluginAdded) {\n clack.log.warn(\n \"Could not add Sentry Gradle plugin to your app's build.gradle file. You'll have to add it manually.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#install\",\n );\n }\n Sentry.setTag('gradle-plugin-added', pluginAdded);\n\n // ======== STEP 2. Configure Sentry SDK via AndroidManifest ============\n clack.log.step(\n `Configuring Sentry SDK via ${chalk.cyan('AndroidManifest.xml')}`,\n );\n const appDir = path.dirname(appFile);\n const manifestFile = path.join(appDir, 'src', 'main', 'AndroidManifest.xml');\n\n const manifestUpdated = traceStep('Update Android Manifest', () =>\n manifest.addManifestSnippet(\n manifestFile,\n selectedProject.keys[0].dsn.public,\n ),\n );\n if (!manifestUpdated) {\n clack.log.warn(\n \"Could not configure the Sentry SDK. You'll have to do it manually.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#configure\",\n );\n }\n Sentry.setTag('android-manifest-updated', manifestUpdated);\n\n // ======== STEP 3. Patch Main Activity with a test error snippet ============\n clack.log.step(\n `Patching ${chalk.bold('Main Activity')} with a test error snippet.`,\n );\n const mainActivity = traceStep('Find Main Activity', () =>\n manifest.getMainActivity(manifestFile),\n );\n let packageName = mainActivity.packageName;\n if (!packageName) {\n // if no package name in AndroidManifest, look into gradle script\n packageName = gradle.getNamespace(appFile);\n }\n const activityName = mainActivity.activityName;\n Sentry.setTag('has-activity-name', !!activityName);\n Sentry.setTag('has-package-name', !!packageName);\n if (!activityName || !packageName) {\n clack.log.warn(\n \"Could not find Activity with intent action MAIN. You'll have to manually verify the setup.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#verify\",\n );\n Sentry.captureException('Could not find Main Activity');\n } else {\n const packageNameStable = packageName;\n const activityFile = traceStep('Find Main Activity Source File', () =>\n codetools.findActivitySourceFile(appDir, packageNameStable, activityName),\n );\n\n const activityPatched = traceStep('Patch Main Activity', () =>\n codetools.patchMainActivity(activityFile),\n );\n if (!activityPatched) {\n clack.log.warn(\n \"Could not patch main activity. You'll have to manually verify the setup.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#verify\",\n );\n }\n Sentry.setTag('main-activity-patched', activityPatched);\n }\n\n // ======== STEP 4. Add sentry-cli config file ============\n clack.log.step(\n `Configuring ${chalk.bold('proguard mappings upload')} via the ${chalk.cyan(\n 'sentry.properties',\n )} file.`,\n );\n\n await addSentryCliConfig({ authToken }, proguardMappingCliSetupConfig);\n\n // ======== OUTRO ========\n const issuesPageLink = selfHosted\n ? `${sentryUrl}organizations/${selectedProject.organization.slug}/issues/?project=${selectedProject.id}`\n : `https://${selectedProject.organization.slug}.sentry.io/issues/?project=${selectedProject.id}`;\n\n clack.outro(`\n${chalk.greenBright('Successfully installed the Sentry Android SDK!')}\n\n${chalk.cyan(\n `You can validate your setup by launching your application and checking Sentry issues page afterwards\n${issuesPageLink}`,\n)}\n\nCheck out the SDK documentation for further configuration:\nhttps://docs.sentry.io/platforms/android/\n `);\n}\n\n//find files with the given extension\nfunction findFilesWithExtensions(\n dir: string,\n extensions: string[],\n filesWithExtensions: string[] = [],\n): string[] {\n const cwd = process.cwd();\n const files = fs.readdirSync(dir, { withFileTypes: true });\n for (const file of files) {\n if (file.isDirectory()) {\n const childDir = path.join(dir, file.name);\n findFilesWithExtensions(childDir, extensions, filesWithExtensions);\n } else if (extensions.some((ext) => file.name.endsWith(ext))) {\n filesWithExtensions.push(path.relative(cwd, path.join(dir, file.name)));\n }\n }\n return filesWithExtensions;\n}\n"]}
1
+ {"version":3,"file":"android-wizard.js","sourceRoot":"","sources":["../../../src/android/android-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport * as fs from 'fs';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport * as Sentry from '@sentry/node';\nimport chalk from 'chalk';\nimport * as path from 'path';\nimport { traceStep, withTelemetry } from '../telemetry';\nimport {\n CliSetupConfig,\n abort,\n addSentryCliConfig,\n confirmContinueIfNoOrDirtyGitRepo,\n getOrAskForProjectData,\n printWelcome,\n propertiesCliSetupConfig,\n} from '../utils/clack';\nimport { WizardOptions } from '../utils/types';\nimport * as codetools from './code-tools';\nimport * as gradle from './gradle';\nimport * as manifest from './manifest';\n\nconst proguardMappingCliSetupConfig: CliSetupConfig = {\n ...propertiesCliSetupConfig,\n name: 'proguard mappings',\n};\n\nexport async function runAndroidWizard(options: WizardOptions): Promise<void> {\n return withTelemetry(\n {\n enabled: options.telemetryEnabled,\n integration: 'android',\n wizardOptions: options,\n },\n () => runAndroidWizardWithTelemetry(options),\n );\n}\n\nasync function runAndroidWizardWithTelemetry(\n options: WizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry Android Wizard',\n promoCode: options.promoCode,\n });\n\n await confirmContinueIfNoOrDirtyGitRepo({\n ignoreGitChanges: options.ignoreGitChanges,\n cwd: undefined,\n });\n\n const projectDir = process.cwd();\n const buildGradleFiles = findFilesWithExtensions(projectDir, [\n '.gradle',\n 'gradle.kts',\n ]);\n\n if (!buildGradleFiles || buildGradleFiles.length === 0) {\n clack.log.error(\n 'No Gradle project found. Please run this command from the root of your project.',\n );\n Sentry.captureException('No Gradle project found');\n await abort();\n return;\n }\n\n const appFile = await traceStep('Select App File', () =>\n gradle.selectAppFile(buildGradleFiles),\n );\n\n const { selectedProject, selfHosted, sentryUrl, authToken } =\n await getOrAskForProjectData(options, 'android');\n\n // ======== STEP 1. Add Sentry Gradle Plugin to build.gradle(.kts) ============\n clack.log.step(\n `Adding ${chalk.bold('Sentry Gradle plugin')} to your app's ${chalk.cyan(\n 'build.gradle',\n )} file.`,\n );\n const pluginAdded = await traceStep('Add Gradle Plugin', () =>\n gradle.addGradlePlugin(\n appFile,\n selectedProject.organization.slug,\n selectedProject.slug,\n ),\n );\n if (!pluginAdded) {\n clack.log.warn(\n \"Could not add Sentry Gradle plugin to your app's build.gradle file. You'll have to add it manually.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#install\",\n );\n }\n Sentry.setTag('gradle-plugin-added', pluginAdded);\n\n // ======== STEP 2. Configure Sentry SDK via AndroidManifest ============\n clack.log.step(\n `Configuring Sentry SDK via ${chalk.cyan('AndroidManifest.xml')}`,\n );\n const appDir = path.dirname(appFile);\n const manifestFile = path.join(appDir, 'src', 'main', 'AndroidManifest.xml');\n\n const manifestUpdated = traceStep('Update Android Manifest', () =>\n manifest.addManifestSnippet(\n manifestFile,\n selectedProject.keys[0].dsn.public,\n ),\n );\n if (!manifestUpdated) {\n clack.log.warn(\n \"Could not configure the Sentry SDK. You'll have to do it manually.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#configure\",\n );\n }\n Sentry.setTag('android-manifest-updated', manifestUpdated);\n\n // ======== STEP 3. Patch Main Activity with a test error snippet ============\n clack.log.step(\n `Patching ${chalk.bold('Main Activity')} with a test error snippet.`,\n );\n const mainActivity = traceStep('Find Main Activity', () =>\n manifest.getMainActivity(manifestFile),\n );\n let packageName = mainActivity.packageName;\n if (!packageName) {\n // if no package name in AndroidManifest, look into gradle script\n packageName = gradle.getNamespace(appFile);\n }\n const activityName = mainActivity.activityName;\n Sentry.setTag('has-activity-name', !!activityName);\n Sentry.setTag('has-package-name', !!packageName);\n if (!activityName || !packageName) {\n clack.log.warn(\n \"Could not find Activity with intent action MAIN. You'll have to manually verify the setup.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#verify\",\n );\n Sentry.captureException('Could not find Main Activity');\n } else {\n const packageNameStable = packageName;\n const activityFile = traceStep('Find Main Activity Source File', () =>\n codetools.findActivitySourceFile(appDir, packageNameStable, activityName),\n );\n\n const activityPatched = traceStep('Patch Main Activity', () =>\n codetools.patchMainActivity(activityFile),\n );\n if (!activityPatched) {\n clack.log.warn(\n \"Could not patch main activity. You'll have to manually verify the setup.\\nPlease follow the instructions at https://docs.sentry.io/platforms/android/#verify\",\n );\n }\n Sentry.setTag('main-activity-patched', activityPatched);\n }\n\n // ======== STEP 4. Add sentry-cli config file ============\n clack.log.step(\n `Configuring ${chalk.bold('proguard mappings upload')} via the ${chalk.cyan(\n 'sentry.properties',\n )} file.`,\n );\n\n await addSentryCliConfig({ authToken }, proguardMappingCliSetupConfig);\n\n // ======== OUTRO ========\n const issuesPageLink = selfHosted\n ? `${sentryUrl}organizations/${selectedProject.organization.slug}/issues/?project=${selectedProject.id}`\n : `https://${selectedProject.organization.slug}.sentry.io/issues/?project=${selectedProject.id}`;\n\n clack.outro(`\n${chalk.greenBright('Successfully installed the Sentry Android SDK!')}\n\n${chalk.cyan(\n `You can validate your setup by launching your application and checking Sentry issues page afterwards\n${issuesPageLink}`,\n)}\n\nCheck out the SDK documentation for further configuration:\nhttps://docs.sentry.io/platforms/android/\n `);\n}\n\n//find files with the given extension\nfunction findFilesWithExtensions(\n dir: string,\n extensions: string[],\n filesWithExtensions: string[] = [],\n): string[] {\n const cwd = process.cwd();\n const files = fs.readdirSync(dir, { withFileTypes: true });\n for (const file of files) {\n if (file.isDirectory()) {\n const childDir = path.join(dir, file.name);\n findFilesWithExtensions(childDir, extensions, filesWithExtensions);\n } else if (extensions.some((ext) => file.name.endsWith(ext))) {\n filesWithExtensions.push(path.relative(cwd, path.join(dir, file.name)));\n }\n }\n return filesWithExtensions;\n}\n"]}
@@ -30,7 +30,7 @@ exports.getLastImportLineLocation = exports.patchMainActivity = exports.findActi
30
30
  const fs = __importStar(require("fs"));
31
31
  const path = __importStar(require("path"));
32
32
  const Sentry = __importStar(require("@sentry/node"));
33
- // @ts-ignore - clack is ESM and TS complains about that. It works though
33
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
34
34
  const clack = __importStar(require("@clack/prompts"));
35
35
  const chalk_1 = __importDefault(require("chalk"));
36
36
  const templates_1 = require("./templates");
@@ -1 +1 @@
1
- {"version":3,"file":"code-tools.js","sourceRoot":"","sources":["../../../src/android/code-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as Sentry from '@sentry/node';\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport {\n sentryImport,\n sentryImportKt,\n testErrorSnippet,\n testErrorSnippetKt,\n} from './templates';\nimport { findFile } from '../utils/ast-utils';\n\n/**\n * Looks in src/main/java or src/main/kotlin for the specified {@link packageName} and\n * {@link activityName} by concatenating them. For example:\n *\n * src/\n * main/\n * java/ or kotlin/\n * my.package.name/\n * ui/\n * MainActivity.kt\n *\n * src/main/java can contain both .java and .kt sources, whilst src/main/kotlin only .kt\n *\n * @param appDir\n * @param packageName\n * @param activityName\n * @returns path to the Main Activity\n */\nexport function findActivitySourceFile(\n appDir: string,\n packageName: string,\n activityName: string,\n): string | undefined {\n const javaSrcDir = path.join(appDir, 'src', 'main', 'java');\n let possibleActivityPath;\n // if activity name starts with a dot, this means we need to concat packagename with it, otherwise\n // the package name is already specified in the activity name itself\n const packageNameParts = activityName.startsWith('.')\n ? packageName.split('.')\n : [];\n const activityNameParts = activityName.split('.');\n\n if (fs.existsSync(javaSrcDir)) {\n possibleActivityPath = findFile(\n path.join(javaSrcDir, ...packageNameParts, ...activityNameParts),\n ['.kt', '.java'],\n );\n }\n\n if (!possibleActivityPath || !fs.existsSync(possibleActivityPath)) {\n const kotlinSrcDir = path.join(appDir, 'src', 'main', 'kotlin');\n if (fs.existsSync(kotlinSrcDir)) {\n possibleActivityPath = findFile(\n path.join(kotlinSrcDir, ...packageNameParts, ...activityNameParts),\n ['.kt'],\n );\n }\n }\n return possibleActivityPath;\n}\n\n/**\n * Patches Main Activity with the test error code snippet by the specified path {@link activityFile}.\n * Finds activity's `onCreate` method, adds the snippet and necessary imports.\n *\n * ```kotlin\n * import something\n * import something.something\n * import io.sentry.Sentry <-- this is added by us\n *\n * override fun onCreate(savedInstanceState: Bundle?) {\n * super.onCreate(savedInstanceState)\n * // the snippet goes here <--\n * doSomething()\n * }\n * ```\n *\n * @param activityFile\n * @returns true if successfully patched, false otherwise\n */\nexport function patchMainActivity(activityFile: string | undefined): boolean {\n if (!activityFile || !fs.existsSync(activityFile)) {\n clack.log.warn('No main activity source file found in filesystem.');\n Sentry.captureException('No main activity source file');\n return false;\n }\n\n const activityContent = fs.readFileSync(activityFile, 'utf8');\n\n if (/import\\s+io\\.sentry\\.Sentry;?/i.test(activityContent)) {\n // sentry is already configured\n clack.log.success(\n chalk.greenBright(\n `${chalk.bold(\n 'Main Activity',\n )} is already patched with test error snippet.`,\n ),\n );\n return true;\n }\n\n const importIndex = getLastImportLineLocation(activityContent);\n\n let newActivityContent;\n if (activityFile.endsWith('.kt')) {\n newActivityContent =\n activityContent.slice(0, importIndex) +\n sentryImportKt +\n activityContent.slice(importIndex);\n } else {\n newActivityContent =\n activityContent.slice(0, importIndex) +\n sentryImport +\n activityContent.slice(importIndex);\n }\n\n const onCreateMatch = /super\\.onCreate\\(.*?\\);?/i.exec(newActivityContent);\n if (!onCreateMatch) {\n clack.log.warn('No onCreate method found in main activity.');\n Sentry.captureException('No onCreate method');\n return false;\n }\n\n const onCreateIndex = onCreateMatch.index + onCreateMatch[0].length;\n if (activityFile.endsWith('.kt')) {\n newActivityContent =\n newActivityContent.slice(0, onCreateIndex) +\n testErrorSnippetKt +\n newActivityContent.slice(onCreateIndex);\n } else {\n newActivityContent =\n newActivityContent.slice(0, onCreateIndex) +\n testErrorSnippet +\n newActivityContent.slice(onCreateIndex);\n }\n fs.writeFileSync(activityFile, newActivityContent, 'utf8');\n\n clack.log.success(\n chalk.greenBright(\n `Patched ${chalk.bold(\n 'Main Activity',\n )} with the Sentry test error snippet.`,\n ),\n );\n\n return true;\n}\n\n/**\n * Returns the string index of the last import statement in the given code file.\n * Works for both Java and Kotlin import statements.\n *\n * @param sourceCode\n * @returns the insert index, or 0 if none found.\n */\nexport function getLastImportLineLocation(sourceCode: string): number {\n const importRegex = /import(?:\\sstatic)?\\s+[\\w.*]+(?: as [\\w.]+)?;?/gim;\n\n let importsMatch = importRegex.exec(sourceCode);\n let importIndex = 0;\n while (importsMatch) {\n importIndex = importsMatch.index + importsMatch[0].length + 1;\n importsMatch = importRegex.exec(sourceCode);\n }\n return importIndex;\n}\n"]}
1
+ {"version":3,"file":"code-tools.js","sourceRoot":"","sources":["../../../src/android/code-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as Sentry from '@sentry/node';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport {\n sentryImport,\n sentryImportKt,\n testErrorSnippet,\n testErrorSnippetKt,\n} from './templates';\nimport { findFile } from '../utils/ast-utils';\n\n/**\n * Looks in src/main/java or src/main/kotlin for the specified {@link packageName} and\n * {@link activityName} by concatenating them. For example:\n *\n * src/\n * main/\n * java/ or kotlin/\n * my.package.name/\n * ui/\n * MainActivity.kt\n *\n * src/main/java can contain both .java and .kt sources, whilst src/main/kotlin only .kt\n *\n * @param appDir\n * @param packageName\n * @param activityName\n * @returns path to the Main Activity\n */\nexport function findActivitySourceFile(\n appDir: string,\n packageName: string,\n activityName: string,\n): string | undefined {\n const javaSrcDir = path.join(appDir, 'src', 'main', 'java');\n let possibleActivityPath;\n // if activity name starts with a dot, this means we need to concat packagename with it, otherwise\n // the package name is already specified in the activity name itself\n const packageNameParts = activityName.startsWith('.')\n ? packageName.split('.')\n : [];\n const activityNameParts = activityName.split('.');\n\n if (fs.existsSync(javaSrcDir)) {\n possibleActivityPath = findFile(\n path.join(javaSrcDir, ...packageNameParts, ...activityNameParts),\n ['.kt', '.java'],\n );\n }\n\n if (!possibleActivityPath || !fs.existsSync(possibleActivityPath)) {\n const kotlinSrcDir = path.join(appDir, 'src', 'main', 'kotlin');\n if (fs.existsSync(kotlinSrcDir)) {\n possibleActivityPath = findFile(\n path.join(kotlinSrcDir, ...packageNameParts, ...activityNameParts),\n ['.kt'],\n );\n }\n }\n return possibleActivityPath;\n}\n\n/**\n * Patches Main Activity with the test error code snippet by the specified path {@link activityFile}.\n * Finds activity's `onCreate` method, adds the snippet and necessary imports.\n *\n * ```kotlin\n * import something\n * import something.something\n * import io.sentry.Sentry <-- this is added by us\n *\n * override fun onCreate(savedInstanceState: Bundle?) {\n * super.onCreate(savedInstanceState)\n * // the snippet goes here <--\n * doSomething()\n * }\n * ```\n *\n * @param activityFile\n * @returns true if successfully patched, false otherwise\n */\nexport function patchMainActivity(activityFile: string | undefined): boolean {\n if (!activityFile || !fs.existsSync(activityFile)) {\n clack.log.warn('No main activity source file found in filesystem.');\n Sentry.captureException('No main activity source file');\n return false;\n }\n\n const activityContent = fs.readFileSync(activityFile, 'utf8');\n\n if (/import\\s+io\\.sentry\\.Sentry;?/i.test(activityContent)) {\n // sentry is already configured\n clack.log.success(\n chalk.greenBright(\n `${chalk.bold(\n 'Main Activity',\n )} is already patched with test error snippet.`,\n ),\n );\n return true;\n }\n\n const importIndex = getLastImportLineLocation(activityContent);\n\n let newActivityContent;\n if (activityFile.endsWith('.kt')) {\n newActivityContent =\n activityContent.slice(0, importIndex) +\n sentryImportKt +\n activityContent.slice(importIndex);\n } else {\n newActivityContent =\n activityContent.slice(0, importIndex) +\n sentryImport +\n activityContent.slice(importIndex);\n }\n\n const onCreateMatch = /super\\.onCreate\\(.*?\\);?/i.exec(newActivityContent);\n if (!onCreateMatch) {\n clack.log.warn('No onCreate method found in main activity.');\n Sentry.captureException('No onCreate method');\n return false;\n }\n\n const onCreateIndex = onCreateMatch.index + onCreateMatch[0].length;\n if (activityFile.endsWith('.kt')) {\n newActivityContent =\n newActivityContent.slice(0, onCreateIndex) +\n testErrorSnippetKt +\n newActivityContent.slice(onCreateIndex);\n } else {\n newActivityContent =\n newActivityContent.slice(0, onCreateIndex) +\n testErrorSnippet +\n newActivityContent.slice(onCreateIndex);\n }\n fs.writeFileSync(activityFile, newActivityContent, 'utf8');\n\n clack.log.success(\n chalk.greenBright(\n `Patched ${chalk.bold(\n 'Main Activity',\n )} with the Sentry test error snippet.`,\n ),\n );\n\n return true;\n}\n\n/**\n * Returns the string index of the last import statement in the given code file.\n * Works for both Java and Kotlin import statements.\n *\n * @param sourceCode\n * @returns the insert index, or 0 if none found.\n */\nexport function getLastImportLineLocation(sourceCode: string): number {\n const importRegex = /import(?:\\sstatic)?\\s+[\\w.*]+(?: as [\\w.]+)?;?/gim;\n\n let importsMatch = importRegex.exec(sourceCode);\n let importIndex = 0;\n while (importsMatch) {\n importIndex = importsMatch.index + importsMatch[0].length + 1;\n importsMatch = importRegex.exec(sourceCode);\n }\n return importIndex;\n}\n"]}
@@ -29,11 +29,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.getNamespace = exports.addGradlePlugin = exports.selectAppFile = void 0;
30
30
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
31
31
  const fs = __importStar(require("fs"));
32
- const clack_utils_1 = require("../utils/clack-utils");
32
+ const clack_1 = require("../utils/clack");
33
33
  const templates_1 = require("./templates");
34
34
  const bash = __importStar(require("../utils/bash"));
35
35
  const Sentry = __importStar(require("@sentry/node"));
36
- // @ts-ignore - clack is ESM and TS complains about that. It works though
36
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
37
37
  const clack = __importStar(require("@clack/prompts"));
38
38
  const chalk_1 = __importDefault(require("chalk"));
39
39
  const release_registry_1 = require("../utils/release-registry");
@@ -63,7 +63,7 @@ async function selectAppFile(buildGradleFiles) {
63
63
  }
64
64
  if (appFiles.length === 0) {
65
65
  Sentry.setTag('custom-build-logic', true);
66
- const appFile = await (0, clack_utils_1.abortIfCancelled)(clack.text({
66
+ const appFile = await (0, clack_1.abortIfCancelled)(clack.text({
67
67
  message: `Unable to find your app's directory.
68
68
  Please enter the relative path to your app's build.gradle file from the root project`,
69
69
  placeholder: 'app/build.gradle.kts',
@@ -81,7 +81,7 @@ async function selectAppFile(buildGradleFiles) {
81
81
  }
82
82
  else {
83
83
  Sentry.setTag('multiple-projects', true);
84
- appFile = (await (0, clack_utils_1.askForItemSelection)(appFiles, 'Which project do you want to add Sentry to?')).value;
84
+ appFile = (await (0, clack_1.askForItemSelection)(appFiles, 'Which project do you want to add Sentry to?')).value;
85
85
  }
86
86
  Sentry.setTag('custom-build-logic', false);
87
87
  return appFile;
@@ -1 +1 @@
1
- {"version":3,"file":"gradle.js","sourceRoot":"","sources":["../../../src/android/gradle.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport * as fs from 'fs';\nimport { abortIfCancelled, askForItemSelection } from '../utils/clack-utils';\nimport {\n plugin,\n pluginKts,\n pluginsBlock,\n pluginsBlockKts,\n sourceContext,\n sourceContextKts,\n} from './templates';\nimport * as bash from '../utils/bash';\nimport * as Sentry from '@sentry/node';\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport { fetchSdkVersion } from '../utils/release-registry';\n\n/**\n * A Gradle project may contain multiple modules, some of them may be applications, some of them may be libraries.\n * We are only interested in applications. For example:\n *\n * myproject/\n * app/\n * lib1/\n * lib2/\n * wearApp/\n *\n * In this case^ we are interested in app/ and wearApp/\n *\n * @param buildGradleFiles a list of build.gradle(.kts) paths that contain the com.android.application plugin\n * @returns the selected project for setting up\n */\nexport async function selectAppFile(\n buildGradleFiles: string[],\n): Promise<string> {\n const appFiles = [];\n for (let index = 0; index < buildGradleFiles.length; index++) {\n const file = buildGradleFiles[index];\n const text = fs.readFileSync(file, 'utf8');\n if (/\\(?[\"']com\\.android\\.application[\"']\\)?(?!.*\\S)/.test(text)) {\n appFiles.push(file);\n }\n }\n\n if (appFiles.length === 0) {\n Sentry.setTag('custom-build-logic', true);\n const appFile = await abortIfCancelled(\n clack.text({\n message: `Unable to find your app's directory. \n Please enter the relative path to your app's build.gradle file from the root project`,\n placeholder: 'app/build.gradle.kts',\n validate(value) {\n if (!value.includes('.gradle') || !fs.existsSync(value))\n return `Not a valid gradle file.`;\n },\n }),\n );\n return appFile;\n }\n\n let appFile;\n if (appFiles.length === 1) {\n Sentry.setTag('multiple-projects', false);\n appFile = appFiles[0];\n } else {\n Sentry.setTag('multiple-projects', true);\n appFile = (\n await askForItemSelection(\n appFiles,\n 'Which project do you want to add Sentry to?',\n )\n ).value;\n }\n Sentry.setTag('custom-build-logic', false);\n return appFile;\n}\n\n/**\n * Patches a build.gradle(.kts) file that contains `com.android.application` plugin.\n * There are multiple cases we have to handle here:\n * - An existing `plugins {}` block:\n * - We just have to add our plugin inside the block\n * - No existing `plugins {}` block\n * - We have to add the entire block in the beginning of the file, BUT *after imports*\n *\n * For example (2nd case):\n *\n * ```\n * import net.ltgt.gradle.errorprone.errorprone\n *\n * // our plugins block goes here <--\n * plugins {\n * id(\"io.sentry.android.gradle\") version \"3.12.0\"\n * }\n *\n * apply(plugin = \"com.android.application\")\n *\n * android {\n * ...\n * }\n * ```\n *\n * In the end we run `./gradlew` to verify the config is build-able and not broken.\n *\n * @param appFile the selected Gradle application project\n * @returns true if successfully added Sentry Gradle config, false otherwise\n */\nexport async function addGradlePlugin(\n appFile: string,\n orgSlug: string,\n projectSlug: string,\n): Promise<boolean> {\n const gradleScript = fs.readFileSync(appFile, 'utf8');\n\n if (/\\(?[\"']io\\.sentry\\.android\\.gradle[\"']\\)?/.test(gradleScript)) {\n // sentry gradle plugin is already installed\n clack.log.success(\n chalk.greenBright(\n `${chalk.bold(\n 'Sentry Gradle plugin',\n )} is already added to the project.`,\n ),\n );\n maybeAddSourceContextConfig(appFile, gradleScript, orgSlug, projectSlug);\n return true;\n }\n\n const pluginVersion = await fetchSdkVersion(\n 'sentry.java.android.gradle-plugin',\n );\n const pluginsBlockMatch = /plugins\\s*{[^{}]*}/.exec(gradleScript);\n let newGradleScript;\n if (!pluginsBlockMatch) {\n // no \"plugins {}\" block, we can just add our own after imports\n const regex = /import\\s+[\\w.]+/gm;\n let importsMatch = regex.exec(gradleScript);\n let insertIndex = 0;\n while (importsMatch) {\n insertIndex = importsMatch.index + importsMatch[0].length + 1;\n importsMatch = regex.exec(gradleScript);\n }\n\n if (appFile.endsWith('.kts')) {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n pluginsBlockKts(pluginVersion) +\n gradleScript.slice(insertIndex);\n } else {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n pluginsBlock(pluginVersion) +\n gradleScript.slice(insertIndex);\n }\n } else {\n const insertIndex =\n pluginsBlockMatch.index + pluginsBlockMatch[0].length - 1;\n if (appFile.endsWith('.kts')) {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n pluginKts(pluginVersion) +\n gradleScript.slice(insertIndex);\n } else {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n plugin(pluginVersion) +\n gradleScript.slice(insertIndex);\n }\n }\n fs.writeFileSync(appFile, newGradleScript, 'utf8');\n\n maybeAddSourceContextConfig(appFile, newGradleScript, orgSlug, projectSlug);\n\n const buildSpinner = clack.spinner();\n\n buildSpinner.start(\n 'Running ./gradlew to verify changes (this may take a few minutes)...',\n );\n\n try {\n await bash.execute('./gradlew');\n buildSpinner.stop(\n chalk.greenBright(\n `${chalk.bold('Sentry Gradle plugin')} added to the project.`,\n ),\n );\n } catch (e) {\n buildSpinner.stop();\n Sentry.captureException('Gradle Sync failed');\n return false;\n }\n\n return true;\n}\n\n/**\n * Looks for the applications packageName (namespace) in the specified build.gradle(.kts) file.\n *\n * ```\n * android {\n * namespace 'my.package.name' <-- this is what we extract\n *\n * compileSdkVersion = 31\n * ...\n * }\n * ```\n * @param appFile\n * @returns the packageName(namespace) of the app if available\n */\nexport function getNamespace(appFile: string): string | undefined {\n const gradleScript = fs.readFileSync(appFile, 'utf8');\n\n const namespaceMatch = /namespace\\s*=?\\s*['\"]([^'\"]+)['\"]/i.exec(\n gradleScript,\n );\n if (!namespaceMatch || namespaceMatch.length <= 1) {\n clack.log.warn('Unable to determine application package name.');\n Sentry.captureException('No package name');\n return undefined;\n }\n\n const namespace = namespaceMatch[1];\n return namespace;\n}\n\n/**\n * Adds source context configuration to the gradleScript if `sentry {}` block is not yet configured,\n *\n * @param appFile\n * @param gradleScript\n */\nfunction maybeAddSourceContextConfig(\n appFile: string,\n gradleScript: string,\n orgSlug: string,\n projectSlug: string,\n) {\n if (!/sentry\\s*\\{[^}]*\\}/i.test(gradleScript)) {\n // if no sentry {} block is configured, we add our own with source context enabled\n if (appFile.endsWith('.kts')) {\n fs.appendFileSync(\n appFile,\n sourceContextKts(orgSlug, projectSlug),\n 'utf8',\n );\n } else {\n fs.appendFileSync(appFile, sourceContext(orgSlug, projectSlug), 'utf8');\n }\n }\n}\n"]}
1
+ {"version":3,"file":"gradle.js","sourceRoot":"","sources":["../../../src/android/gradle.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport * as fs from 'fs';\nimport { abortIfCancelled, askForItemSelection } from '../utils/clack';\nimport {\n plugin,\n pluginKts,\n pluginsBlock,\n pluginsBlockKts,\n sourceContext,\n sourceContextKts,\n} from './templates';\nimport * as bash from '../utils/bash';\nimport * as Sentry from '@sentry/node';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport { fetchSdkVersion } from '../utils/release-registry';\n\n/**\n * A Gradle project may contain multiple modules, some of them may be applications, some of them may be libraries.\n * We are only interested in applications. For example:\n *\n * myproject/\n * app/\n * lib1/\n * lib2/\n * wearApp/\n *\n * In this case^ we are interested in app/ and wearApp/\n *\n * @param buildGradleFiles a list of build.gradle(.kts) paths that contain the com.android.application plugin\n * @returns the selected project for setting up\n */\nexport async function selectAppFile(\n buildGradleFiles: string[],\n): Promise<string> {\n const appFiles = [];\n for (let index = 0; index < buildGradleFiles.length; index++) {\n const file = buildGradleFiles[index];\n const text = fs.readFileSync(file, 'utf8');\n if (/\\(?[\"']com\\.android\\.application[\"']\\)?(?!.*\\S)/.test(text)) {\n appFiles.push(file);\n }\n }\n\n if (appFiles.length === 0) {\n Sentry.setTag('custom-build-logic', true);\n const appFile = await abortIfCancelled(\n clack.text({\n message: `Unable to find your app's directory. \n Please enter the relative path to your app's build.gradle file from the root project`,\n placeholder: 'app/build.gradle.kts',\n validate(value) {\n if (!value.includes('.gradle') || !fs.existsSync(value))\n return `Not a valid gradle file.`;\n },\n }),\n );\n return appFile;\n }\n\n let appFile;\n if (appFiles.length === 1) {\n Sentry.setTag('multiple-projects', false);\n appFile = appFiles[0];\n } else {\n Sentry.setTag('multiple-projects', true);\n appFile = (\n await askForItemSelection(\n appFiles,\n 'Which project do you want to add Sentry to?',\n )\n ).value;\n }\n Sentry.setTag('custom-build-logic', false);\n return appFile;\n}\n\n/**\n * Patches a build.gradle(.kts) file that contains `com.android.application` plugin.\n * There are multiple cases we have to handle here:\n * - An existing `plugins {}` block:\n * - We just have to add our plugin inside the block\n * - No existing `plugins {}` block\n * - We have to add the entire block in the beginning of the file, BUT *after imports*\n *\n * For example (2nd case):\n *\n * ```\n * import net.ltgt.gradle.errorprone.errorprone\n *\n * // our plugins block goes here <--\n * plugins {\n * id(\"io.sentry.android.gradle\") version \"3.12.0\"\n * }\n *\n * apply(plugin = \"com.android.application\")\n *\n * android {\n * ...\n * }\n * ```\n *\n * In the end we run `./gradlew` to verify the config is build-able and not broken.\n *\n * @param appFile the selected Gradle application project\n * @returns true if successfully added Sentry Gradle config, false otherwise\n */\nexport async function addGradlePlugin(\n appFile: string,\n orgSlug: string,\n projectSlug: string,\n): Promise<boolean> {\n const gradleScript = fs.readFileSync(appFile, 'utf8');\n\n if (/\\(?[\"']io\\.sentry\\.android\\.gradle[\"']\\)?/.test(gradleScript)) {\n // sentry gradle plugin is already installed\n clack.log.success(\n chalk.greenBright(\n `${chalk.bold(\n 'Sentry Gradle plugin',\n )} is already added to the project.`,\n ),\n );\n maybeAddSourceContextConfig(appFile, gradleScript, orgSlug, projectSlug);\n return true;\n }\n\n const pluginVersion = await fetchSdkVersion(\n 'sentry.java.android.gradle-plugin',\n );\n const pluginsBlockMatch = /plugins\\s*{[^{}]*}/.exec(gradleScript);\n let newGradleScript;\n if (!pluginsBlockMatch) {\n // no \"plugins {}\" block, we can just add our own after imports\n const regex = /import\\s+[\\w.]+/gm;\n let importsMatch = regex.exec(gradleScript);\n let insertIndex = 0;\n while (importsMatch) {\n insertIndex = importsMatch.index + importsMatch[0].length + 1;\n importsMatch = regex.exec(gradleScript);\n }\n\n if (appFile.endsWith('.kts')) {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n pluginsBlockKts(pluginVersion) +\n gradleScript.slice(insertIndex);\n } else {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n pluginsBlock(pluginVersion) +\n gradleScript.slice(insertIndex);\n }\n } else {\n const insertIndex =\n pluginsBlockMatch.index + pluginsBlockMatch[0].length - 1;\n if (appFile.endsWith('.kts')) {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n pluginKts(pluginVersion) +\n gradleScript.slice(insertIndex);\n } else {\n newGradleScript =\n gradleScript.slice(0, insertIndex) +\n plugin(pluginVersion) +\n gradleScript.slice(insertIndex);\n }\n }\n fs.writeFileSync(appFile, newGradleScript, 'utf8');\n\n maybeAddSourceContextConfig(appFile, newGradleScript, orgSlug, projectSlug);\n\n const buildSpinner = clack.spinner();\n\n buildSpinner.start(\n 'Running ./gradlew to verify changes (this may take a few minutes)...',\n );\n\n try {\n await bash.execute('./gradlew');\n buildSpinner.stop(\n chalk.greenBright(\n `${chalk.bold('Sentry Gradle plugin')} added to the project.`,\n ),\n );\n } catch (e) {\n buildSpinner.stop();\n Sentry.captureException('Gradle Sync failed');\n return false;\n }\n\n return true;\n}\n\n/**\n * Looks for the applications packageName (namespace) in the specified build.gradle(.kts) file.\n *\n * ```\n * android {\n * namespace 'my.package.name' <-- this is what we extract\n *\n * compileSdkVersion = 31\n * ...\n * }\n * ```\n * @param appFile\n * @returns the packageName(namespace) of the app if available\n */\nexport function getNamespace(appFile: string): string | undefined {\n const gradleScript = fs.readFileSync(appFile, 'utf8');\n\n const namespaceMatch = /namespace\\s*=?\\s*['\"]([^'\"]+)['\"]/i.exec(\n gradleScript,\n );\n if (!namespaceMatch || namespaceMatch.length <= 1) {\n clack.log.warn('Unable to determine application package name.');\n Sentry.captureException('No package name');\n return undefined;\n }\n\n const namespace = namespaceMatch[1];\n return namespace;\n}\n\n/**\n * Adds source context configuration to the gradleScript if `sentry {}` block is not yet configured,\n *\n * @param appFile\n * @param gradleScript\n */\nfunction maybeAddSourceContextConfig(\n appFile: string,\n gradleScript: string,\n orgSlug: string,\n projectSlug: string,\n) {\n if (!/sentry\\s*\\{[^}]*\\}/i.test(gradleScript)) {\n // if no sentry {} block is configured, we add our own with source context enabled\n if (appFile.endsWith('.kts')) {\n fs.appendFileSync(\n appFile,\n sourceContextKts(orgSlug, projectSlug),\n 'utf8',\n );\n } else {\n fs.appendFileSync(appFile, sourceContext(orgSlug, projectSlug), 'utf8');\n }\n }\n}\n"]}
@@ -30,7 +30,7 @@ exports.getMainActivity = exports.addManifestSnippet = void 0;
30
30
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
31
31
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
32
32
  const fs = __importStar(require("fs"));
33
- // @ts-ignore - clack is ESM and TS complains about that. It works though
33
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
34
34
  const clack = __importStar(require("@clack/prompts"));
35
35
  const Sentry = __importStar(require("@sentry/node"));
36
36
  const templates_1 = require("./templates");
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/android/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport * as fs from 'fs';\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport * as Sentry from '@sentry/node';\nimport { manifest } from './templates';\nimport xml, { Attributes, ElementCompact } from 'xml-js';\nimport chalk from 'chalk';\n\n/**\n * Looks for the closing </application> tag in the manifest and adds the Sentry config after it.\n *\n * For example:\n * ```xml\n * <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n * xmlns:tools=\"http://schemas.android.com/tools\">\n *\n * <application>\n * ...\n * // this is what we add and more\n * <meta-data android:name=\"io.sentry.dsn\" android:value=\"__dsn__\" />\n * </application> <!-- we are looking for this one\n * </manifest>\n * ```\n *\n * @param manifestFile the path to the main AndroidManifest.xml file\n * @param dsn\n * @returns true if successfully patched the manifest, false otherwise\n */\nexport function addManifestSnippet(manifestFile: string, dsn: string): boolean {\n if (!fs.existsSync(manifestFile)) {\n clack.log.warn('AndroidManifest.xml not found.');\n Sentry.captureException('No AndroidManifest file');\n return false;\n }\n\n const manifestContent = fs.readFileSync(manifestFile, 'utf8');\n\n if (/android:name=\"io\\.sentry[^\"]*\"/i.test(manifestContent)) {\n // sentry is already configured\n clack.log.success(chalk.greenBright('Sentry SDK is already configured.'));\n return true;\n }\n\n const applicationMatch = /<\\/application>/i.exec(manifestContent);\n if (!applicationMatch) {\n clack.log.warn('<application> tag not found within the manifest.');\n Sentry.captureException('No <application> tag');\n return false;\n }\n\n const insertionIndex = applicationMatch.index;\n const newContent =\n manifestContent.slice(0, insertionIndex) +\n manifest(dsn) +\n manifestContent.slice(insertionIndex);\n fs.writeFileSync(manifestFile, newContent, 'utf8');\n\n clack.log.success(\n chalk.greenBright(\n `Updated ${chalk.bold(\n 'AndroidManifest.xml',\n )} with the Sentry SDK configuration.`,\n ),\n );\n\n return true;\n}\n\n/**\n * There might be multiple <activity> in the manifest, as well as multiple <activity-alias> with category LAUNCHER,\n * but only one main activity with action MAIN. We are looking for this one by parsing xml and walking it.\n *\n * In addition, older Android versions required to specify the packag name in the manifest,\n * while the new ones - in the Gradle config. So we are just sanity checking if the package name\n * is in the manifest and returning it as well.\n *\n * For example:\n *\n * ```xml\n * <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n * xmlns:tools=\"http://schemas.android.com/tools\"\n * package=\"com.example.sample\">\n *\n * <application>\n * <activity\n * android:name=\"ui.MainActivity\"\n * ...other props>\n * <intent-filter>\n * <action android:name=\"android.intent.action.MAIN\" /> <!-- we are looking for this one\n *\n * <category android:name=\"android.intent.category.LAUNCHER\" />\n * </intent-filter>\n * </activity>\n * </application>\n * </manifest>\n * ```\n *\n * @param manifestFile path to the AndroidManifest.xml file\n * @returns package name (if available in the manifest) + the main activity name\n */\nexport function getMainActivity(manifestFile: string): {\n packageName?: string;\n activityName?: string;\n} {\n if (!fs.existsSync(manifestFile)) {\n clack.log.warn('AndroidManifest.xml not found.');\n Sentry.captureException('No AndroidManifest file');\n return {};\n }\n\n const manifestContent = fs.readFileSync(manifestFile, 'utf8');\n const converted: ElementCompact = xml.xml2js(manifestContent, {\n compact: true,\n });\n const activities: ElementCompact[] | ElementCompact | undefined =\n converted.manifest?.application?.activity;\n const packageName: string | undefined =\n converted.manifest?._attributes?.['package'];\n\n if (!activities) {\n clack.log.warn('No activity found in AndroidManifest.');\n Sentry.captureException('No Activity');\n return {};\n }\n\n let mainActivity;\n if (Array.isArray(activities)) {\n const withIntentFilter = activities.filter((a) => !!a['intent-filter']);\n mainActivity = withIntentFilter.find((a) => isMainActivity(a));\n } else if (isMainActivity(activities)) {\n mainActivity = activities;\n }\n\n if (!mainActivity) {\n clack.log.warn('No main activity found in AndroidManifest.');\n Sentry.captureException('No Main Activity');\n return {};\n }\n\n const attrs = mainActivity._attributes;\n const activityName = attrs?.['android:name'] as string | undefined;\n return { packageName: packageName, activityName: activityName };\n}\n\nfunction isMainActivity(activity: ElementCompact): boolean {\n const intentFilters: ElementCompact[] | ElementCompact =\n activity['intent-filter'];\n if (Array.isArray(intentFilters)) {\n return intentFilters.some((i) => {\n const action: ElementCompact[] | ElementCompact | undefined = i.action;\n return hasMainAction(action);\n });\n } else {\n const action: ElementCompact[] | ElementCompact | undefined =\n intentFilters.action;\n return hasMainAction(action);\n }\n}\n\nfunction hasMainAction(\n action: ElementCompact[] | ElementCompact | undefined,\n): boolean {\n if (!action) {\n return false;\n }\n\n function isMain(attrs?: Attributes): boolean {\n return attrs?.['android:name'] === 'android.intent.action.MAIN';\n }\n\n if (Array.isArray(action)) {\n return action.some((c) => {\n return isMain(c._attributes);\n });\n } else {\n return isMain(action._attributes);\n }\n}\n"]}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/android/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport * as fs from 'fs';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport * as Sentry from '@sentry/node';\nimport { manifest } from './templates';\nimport xml, { Attributes, ElementCompact } from 'xml-js';\nimport chalk from 'chalk';\n\n/**\n * Looks for the closing </application> tag in the manifest and adds the Sentry config after it.\n *\n * For example:\n * ```xml\n * <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n * xmlns:tools=\"http://schemas.android.com/tools\">\n *\n * <application>\n * ...\n * // this is what we add and more\n * <meta-data android:name=\"io.sentry.dsn\" android:value=\"__dsn__\" />\n * </application> <!-- we are looking for this one\n * </manifest>\n * ```\n *\n * @param manifestFile the path to the main AndroidManifest.xml file\n * @param dsn\n * @returns true if successfully patched the manifest, false otherwise\n */\nexport function addManifestSnippet(manifestFile: string, dsn: string): boolean {\n if (!fs.existsSync(manifestFile)) {\n clack.log.warn('AndroidManifest.xml not found.');\n Sentry.captureException('No AndroidManifest file');\n return false;\n }\n\n const manifestContent = fs.readFileSync(manifestFile, 'utf8');\n\n if (/android:name=\"io\\.sentry[^\"]*\"/i.test(manifestContent)) {\n // sentry is already configured\n clack.log.success(chalk.greenBright('Sentry SDK is already configured.'));\n return true;\n }\n\n const applicationMatch = /<\\/application>/i.exec(manifestContent);\n if (!applicationMatch) {\n clack.log.warn('<application> tag not found within the manifest.');\n Sentry.captureException('No <application> tag');\n return false;\n }\n\n const insertionIndex = applicationMatch.index;\n const newContent =\n manifestContent.slice(0, insertionIndex) +\n manifest(dsn) +\n manifestContent.slice(insertionIndex);\n fs.writeFileSync(manifestFile, newContent, 'utf8');\n\n clack.log.success(\n chalk.greenBright(\n `Updated ${chalk.bold(\n 'AndroidManifest.xml',\n )} with the Sentry SDK configuration.`,\n ),\n );\n\n return true;\n}\n\n/**\n * There might be multiple <activity> in the manifest, as well as multiple <activity-alias> with category LAUNCHER,\n * but only one main activity with action MAIN. We are looking for this one by parsing xml and walking it.\n *\n * In addition, older Android versions required to specify the packag name in the manifest,\n * while the new ones - in the Gradle config. So we are just sanity checking if the package name\n * is in the manifest and returning it as well.\n *\n * For example:\n *\n * ```xml\n * <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n * xmlns:tools=\"http://schemas.android.com/tools\"\n * package=\"com.example.sample\">\n *\n * <application>\n * <activity\n * android:name=\"ui.MainActivity\"\n * ...other props>\n * <intent-filter>\n * <action android:name=\"android.intent.action.MAIN\" /> <!-- we are looking for this one\n *\n * <category android:name=\"android.intent.category.LAUNCHER\" />\n * </intent-filter>\n * </activity>\n * </application>\n * </manifest>\n * ```\n *\n * @param manifestFile path to the AndroidManifest.xml file\n * @returns package name (if available in the manifest) + the main activity name\n */\nexport function getMainActivity(manifestFile: string): {\n packageName?: string;\n activityName?: string;\n} {\n if (!fs.existsSync(manifestFile)) {\n clack.log.warn('AndroidManifest.xml not found.');\n Sentry.captureException('No AndroidManifest file');\n return {};\n }\n\n const manifestContent = fs.readFileSync(manifestFile, 'utf8');\n const converted: ElementCompact = xml.xml2js(manifestContent, {\n compact: true,\n });\n const activities: ElementCompact[] | ElementCompact | undefined =\n converted.manifest?.application?.activity;\n const packageName: string | undefined =\n converted.manifest?._attributes?.['package'];\n\n if (!activities) {\n clack.log.warn('No activity found in AndroidManifest.');\n Sentry.captureException('No Activity');\n return {};\n }\n\n let mainActivity;\n if (Array.isArray(activities)) {\n const withIntentFilter = activities.filter((a) => !!a['intent-filter']);\n mainActivity = withIntentFilter.find((a) => isMainActivity(a));\n } else if (isMainActivity(activities)) {\n mainActivity = activities;\n }\n\n if (!mainActivity) {\n clack.log.warn('No main activity found in AndroidManifest.');\n Sentry.captureException('No Main Activity');\n return {};\n }\n\n const attrs = mainActivity._attributes;\n const activityName = attrs?.['android:name'] as string | undefined;\n return { packageName: packageName, activityName: activityName };\n}\n\nfunction isMainActivity(activity: ElementCompact): boolean {\n const intentFilters: ElementCompact[] | ElementCompact =\n activity['intent-filter'];\n if (Array.isArray(intentFilters)) {\n return intentFilters.some((i) => {\n const action: ElementCompact[] | ElementCompact | undefined = i.action;\n return hasMainAction(action);\n });\n } else {\n const action: ElementCompact[] | ElementCompact | undefined =\n intentFilters.action;\n return hasMainAction(action);\n }\n}\n\nfunction hasMainAction(\n action: ElementCompact[] | ElementCompact | undefined,\n): boolean {\n if (!action) {\n return false;\n }\n\n function isMain(attrs?: Attributes): boolean {\n return attrs?.['android:name'] === 'android.intent.action.MAIN';\n }\n\n if (Array.isArray(action)) {\n return action.some((c) => {\n return isMain(c._attributes);\n });\n } else {\n return isMain(action._attributes);\n }\n}\n"]}
@@ -1,2 +1,2 @@
1
- import { WizardOptions } from '../utils/types';
2
- export declare function runAppleWizard(options: WizardOptions): Promise<void>;
1
+ import { AppleWizardOptions } from './options';
2
+ export declare function runAppleWizard(options: AppleWizardOptions): Promise<void>;
@@ -1,52 +1,20 @@
1
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
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  exports.runAppleWizard = void 0;
30
- /* eslint-disable max-lines */
31
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
32
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
33
- /* eslint-disable @typescript-eslint/no-unsafe-call */
34
- /* eslint-disable @typescript-eslint/no-unused-vars */
35
- // @ts-ignore - clack is ESM and TS complains about that. It works though
7
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
36
8
  const prompts_1 = __importDefault(require("@clack/prompts"));
37
- const chalk_1 = __importDefault(require("chalk"));
38
- const fs = __importStar(require("fs"));
39
- const path = __importStar(require("path"));
40
- const xcode_manager_1 = require("./xcode-manager");
41
- const codeTools = __importStar(require("./code-tools"));
42
- const bash = __importStar(require("../utils/bash"));
43
- const SentryUtils = __importStar(require("../utils/sentrycli-utils"));
44
- const Sentry = __importStar(require("@sentry/node"));
45
9
  const telemetry_1 = require("../telemetry");
46
- const cocoapod = __importStar(require("./cocoapod"));
47
- const fastlane = __importStar(require("./fastlane"));
48
- /* eslint-enable @typescript-eslint/no-unused-vars */
49
- const clack_utils_1 = require("../utils/clack-utils");
10
+ const clack_1 = require("../utils/clack");
11
+ const check_installed_cli_1 = require("./check-installed-cli");
12
+ const configure_fastlane_1 = require("./configure-fastlane");
13
+ const configure_package_manager_1 = require("./configure-package-manager");
14
+ const configure_sentry_cli_1 = require("./configure-sentry-cli");
15
+ const configure_xcode_project_1 = require("./configure-xcode-project");
16
+ const inject_code_snippet_1 = require("./inject-code-snippet");
17
+ const lookup_xcode_project_1 = require("./lookup-xcode-project");
50
18
  async function runAppleWizard(options) {
51
19
  return (0, telemetry_1.withTelemetry)({
52
20
  enabled: options.telemetryEnabled,
@@ -56,145 +24,56 @@ async function runAppleWizard(options) {
56
24
  }
57
25
  exports.runAppleWizard = runAppleWizard;
58
26
  async function runAppleWizardWithTelementry(options) {
59
- (0, clack_utils_1.printWelcome)({
27
+ // Define options with defaults
28
+ const projectDir = options.projectDir ?? process.cwd();
29
+ // Step - Welcome Message
30
+ (0, clack_1.printWelcome)({
60
31
  wizardName: 'Sentry Apple Wizard',
61
32
  promoCode: options.promoCode,
62
33
  });
63
- await (0, clack_utils_1.confirmContinueIfNoOrDirtyGitRepo)();
64
- const hasCli = bash.hasSentryCLI();
65
- Sentry.setTag('has-cli', hasCli);
66
- if (!hasCli) {
67
- if (!(await (0, telemetry_1.traceStep)('Ask for SentryCLI', () => (0, clack_utils_1.askToInstallSentryCLI)()))) {
68
- prompts_1.default.log.warn("Without sentry-cli, you won't be able to upload debug symbols to Sentry. You can install it later by following the instructions at https://docs.sentry.io/cli/");
69
- Sentry.setTag('CLI-Installed', false);
70
- }
71
- else {
72
- await bash.installSentryCLI();
73
- Sentry.setTag('CLI-Installed', true);
74
- }
75
- }
76
- const projectDir = process.cwd();
77
- const xcodeProjFiles = searchXcodeProject(projectDir);
78
- if (!xcodeProjFiles || xcodeProjFiles.length === 0) {
79
- prompts_1.default.log.error('No Xcode project found. Please run this command from the root of your project.');
80
- await (0, clack_utils_1.abort)();
81
- return;
82
- }
83
- let xcodeProjFile;
84
- if (xcodeProjFiles.length === 1) {
85
- xcodeProjFile = xcodeProjFiles[0];
86
- Sentry.setTag('multiple-projects', false);
87
- }
88
- else {
89
- Sentry.setTag('multiple-projects', true);
90
- xcodeProjFile = (await (0, telemetry_1.traceStep)('Choose Xcode project', () => (0, clack_utils_1.askForItemSelection)(xcodeProjFiles, 'Which project do you want to add Sentry to?'))).value;
91
- }
92
- const pbxproj = path.join(projectDir, xcodeProjFile, 'project.pbxproj');
93
- if (!fs.existsSync(pbxproj)) {
94
- prompts_1.default.log.error(`No pbxproj found at ${xcodeProjFile}`);
95
- await (0, clack_utils_1.abort)();
96
- return;
97
- }
98
- const { project, apiKey } = await getSentryProjectAndApiKey(options);
99
- const xcProject = new xcode_manager_1.XcodeProject(pbxproj);
100
- const availableTargets = xcProject.getAllTargets();
101
- if (availableTargets.length == 0) {
102
- prompts_1.default.log.error(`No suitable target found in ${xcodeProjFile}`);
103
- Sentry.setTag('No-Target', true);
104
- await (0, clack_utils_1.abort)();
105
- return;
106
- }
107
- const target = availableTargets.length == 1
108
- ? availableTargets[0]
109
- : (await (0, telemetry_1.traceStep)('Choose target', () => (0, clack_utils_1.askForItemSelection)(availableTargets, 'Which target do you want to add Sentry to?'))).value;
110
- SentryUtils.createSentryCLIRC(projectDir, { auth_token: apiKey.token });
111
- prompts_1.default.log.info(`Created a ${chalk_1.default.cyan('.sentryclirc')} file in your project directory to provide an auth token for Sentry CLI.
112
-
113
- It was also added to your ${chalk_1.default.cyan('.gitignore')} file.
114
- Set the ${chalk_1.default.cyan('SENTRY_AUTH_TOKEN')} environment variable in your CI environment. See https://docs.sentry.io/cli/configuration/#auth-token for more information.`);
115
- let hasCocoa = cocoapod.usesCocoaPod(projectDir);
116
- Sentry.setTag('cocoapod-exists', hasCocoa);
117
- if (hasCocoa) {
118
- const pm = (await (0, telemetry_1.traceStep)('Choose a package manager', () => (0, clack_utils_1.askForItemSelection)(['Swift Package Manager', 'CocoaPods'], 'Which package manager would you like to use to add Sentry?'))).value;
119
- hasCocoa = pm === 'CocoaPods';
120
- if (hasCocoa) {
121
- const podAdded = await (0, telemetry_1.traceStep)('Add CocoaPods reference', () => cocoapod.addCocoaPods(projectDir));
122
- Sentry.setTag('cocoapod-added', podAdded);
123
- if (!podAdded) {
124
- prompts_1.default.log.warn("Could not add Sentry pod to your Podfile. You'll have to add it manually.\nPlease follow the instructions at https://docs.sentry.io/platforms/apple/guides/ios/#install");
125
- }
126
- }
127
- }
128
- Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');
129
- (0, telemetry_1.traceStep)('Update Xcode project', () => {
130
- xcProject.updateXcodeProject(project, target, !hasCocoa, true);
34
+ // Step - Git Status Check
35
+ await (0, clack_1.confirmContinueIfNoOrDirtyGitRepo)({
36
+ ignoreGitChanges: options.ignoreGitChanges,
37
+ cwd: projectDir,
38
+ });
39
+ // Step - Sentry CLI Check
40
+ await (0, check_installed_cli_1.checkInstalledCLI)();
41
+ // Step - Xcode Project Lookup
42
+ // This step should be run before the Sentry Project and API Key step
43
+ // because it can abort the wizard if no Xcode project is found.
44
+ const { xcProject, target } = await (0, lookup_xcode_project_1.lookupXcodeProject)({
45
+ projectDir,
46
+ });
47
+ // Step - Sentry Project and API Key
48
+ const { selectedProject, authToken } = await (0, clack_1.getOrAskForProjectData)(options, 'apple-ios');
49
+ // Step - Sentry CLI Configuration Setup
50
+ (0, configure_sentry_cli_1.configureSentryCLI)({
51
+ projectDir,
52
+ authToken: authToken,
53
+ });
54
+ // Step - Set up Package Manager
55
+ const { shouldUseSPM } = await (0, configure_package_manager_1.configurePackageManager)({
56
+ projectDir,
57
+ });
58
+ // Step - Configure Xcode Project
59
+ (0, configure_xcode_project_1.configureXcodeProject)({
60
+ xcProject,
61
+ project: selectedProject,
62
+ target,
63
+ shouldUseSPM,
131
64
  });
132
- const codeAdded = (0, telemetry_1.traceStep)('Add code snippet', () => {
133
- const files = xcProject.filesForTarget(target);
134
- if (files === undefined || files.length == 0)
135
- return false;
136
- return codeTools.addCodeSnippetToProject(projectDir, files, project.keys[0].dsn.public);
65
+ // Step - Add Code Snippet
66
+ (0, inject_code_snippet_1.injectCodeSnippet)({
67
+ project: xcProject,
68
+ target,
69
+ dsn: selectedProject.keys[0].dsn.public,
70
+ });
71
+ // Step - Fastlane Configuration
72
+ await (0, configure_fastlane_1.configureFastlane)({
73
+ projectDir,
74
+ orgSlug: selectedProject.organization.slug,
75
+ projectSlug: selectedProject.slug,
137
76
  });
138
- Sentry.setTag('Snippet-Added', codeAdded);
139
- if (!codeAdded) {
140
- prompts_1.default.log.warn('Added the Sentry dependency to your project but could not add the Sentry code snippet. Please add the code snipped manually by following the docs: https://docs.sentry.io/platforms/apple/guides/ios/#configure');
141
- }
142
- const hasFastlane = fastlane.fastFile(projectDir);
143
- Sentry.setTag('fastlane-exists', hasFastlane);
144
- if (hasFastlane) {
145
- const addLane = await prompts_1.default.confirm({
146
- message: 'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',
147
- });
148
- Sentry.setTag('fastlane-desired', addLane);
149
- if (addLane) {
150
- const added = await (0, telemetry_1.traceStep)('Configure fastlane', () => fastlane.addSentryToFastlane(projectDir, project.organization.slug, project.slug));
151
- Sentry.setTag('fastlane-added', added);
152
- if (added) {
153
- prompts_1.default.log.step('A new step was added to your fastlane file. Now and you build your project with fastlane, debug symbols and source context will be uploaded to Sentry.');
154
- }
155
- else {
156
- prompts_1.default.log.warn('Could not edit your fastlane file to upload debug symbols to Sentry. Please follow the instructions at https://docs.sentry.io/platforms/apple/guides/ios/dsym/#fastlane');
157
- }
158
- }
159
- }
160
77
  prompts_1.default.log.success('Sentry was successfully added to your project! Run your project to send your first event to Sentry. Go to Sentry.io to see whether everything is working fine.');
161
78
  }
162
- //Prompt for Sentry project and API key
163
- async function getSentryProjectAndApiKey(options) {
164
- const { selectedProject, authToken } = await (0, clack_utils_1.getOrAskForProjectData)(options);
165
- return { project: selectedProject, apiKey: { token: authToken } };
166
- }
167
- function searchXcodeProject(at) {
168
- const projs = findFilesWithExtension(at, '.xcodeproj');
169
- if (projs.length > 0) {
170
- return projs;
171
- }
172
- const workspace = findFilesWithExtension(at, '.xcworkspace');
173
- if (workspace.length == 0) {
174
- return [];
175
- }
176
- const xsworkspacedata = path.join(at, workspace[0], 'contents.xcworkspacedata');
177
- if (!fs.existsSync(xsworkspacedata)) {
178
- return [];
179
- }
180
- const groupRegex = /location *= *"group:([^"]+)"/gim;
181
- const content = fs.readFileSync(xsworkspacedata, 'utf8');
182
- let matches = groupRegex.exec(content);
183
- while (matches) {
184
- const group = matches[1];
185
- const groupPath = path.join(at, group);
186
- if (!group.endsWith('Pods.xcodeproj') &&
187
- group.endsWith('.xcodeproj') &&
188
- fs.existsSync(groupPath)) {
189
- projs.push(group);
190
- }
191
- matches = groupRegex.exec(content);
192
- }
193
- return projs;
194
- }
195
- //find files with the given extension
196
- function findFilesWithExtension(dir, extension) {
197
- const files = fs.readdirSync(dir);
198
- return files.filter((file) => file.endsWith(extension));
199
- }
200
79
  //# sourceMappingURL=apple-wizard.js.map