@sentry/wizard 3.10.0 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CHANGELOG.md +54 -7
  2. package/dist/lib/Constants.d.ts +1 -0
  3. package/dist/lib/Constants.js +5 -0
  4. package/dist/lib/Constants.js.map +1 -1
  5. package/dist/lib/Steps/ChooseIntegration.js +8 -4
  6. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  7. package/dist/lib/Steps/Integrations/Android.d.ts +9 -0
  8. package/dist/lib/Steps/Integrations/Android.js +86 -0
  9. package/dist/lib/Steps/Integrations/Android.js.map +1 -0
  10. package/dist/lib/Steps/Integrations/ReactNative.js +3 -3
  11. package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
  12. package/dist/lib/Steps/PromptForParameters.js +36 -3
  13. package/dist/lib/Steps/PromptForParameters.js.map +1 -1
  14. package/dist/lib/Steps/SentryProjectSelector.js +1 -1
  15. package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
  16. package/dist/package.json +4 -3
  17. package/dist/src/android/android-wizard.d.ts +2 -0
  18. package/dist/src/android/android-wizard.js +225 -0
  19. package/dist/src/android/android-wizard.js.map +1 -0
  20. package/dist/src/android/code-tools.d.ts +47 -0
  21. package/dist/src/android/code-tools.js +173 -0
  22. package/dist/src/android/code-tools.js.map +1 -0
  23. package/dist/src/android/gradle.d.ts +62 -0
  24. package/dist/src/android/gradle.js +286 -0
  25. package/dist/src/android/gradle.js.map +1 -0
  26. package/dist/src/android/manifest.d.ts +57 -0
  27. package/dist/src/android/manifest.js +183 -0
  28. package/dist/src/android/manifest.js.map +1 -0
  29. package/dist/src/android/templates.d.ts +11 -0
  30. package/dist/src/android/templates.js +34 -0
  31. package/dist/src/android/templates.js.map +1 -0
  32. package/dist/src/apple/apple-wizard.js +123 -64
  33. package/dist/src/apple/apple-wizard.js.map +1 -1
  34. package/dist/src/apple/cocoapod.js +4 -3
  35. package/dist/src/apple/cocoapod.js.map +1 -1
  36. package/dist/src/apple/code-tools.d.ts +1 -1
  37. package/dist/src/apple/code-tools.js +43 -19
  38. package/dist/src/apple/code-tools.js.map +1 -1
  39. package/dist/src/apple/fastlane.d.ts +1 -1
  40. package/dist/src/apple/fastlane.js +12 -6
  41. package/dist/src/apple/fastlane.js.map +1 -1
  42. package/dist/src/apple/templates.d.ts +2 -2
  43. package/dist/src/apple/templates.js +4 -4
  44. package/dist/src/apple/templates.js.map +1 -1
  45. package/dist/src/apple/xcode-manager.d.ts +19 -3
  46. package/dist/src/apple/xcode-manager.js +126 -24
  47. package/dist/src/apple/xcode-manager.js.map +1 -1
  48. package/dist/src/nextjs/nextjs-wizard.js +49 -11
  49. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  50. package/dist/src/nextjs/templates.d.ts +2 -0
  51. package/dist/src/nextjs/templates.js +6 -2
  52. package/dist/src/nextjs/templates.js.map +1 -1
  53. package/dist/src/remix/remix-wizard.js +10 -20
  54. package/dist/src/remix/remix-wizard.js.map +1 -1
  55. package/dist/src/sourcemaps/sourcemaps-wizard.js +26 -13
  56. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  57. package/dist/src/sourcemaps/tools/nextjs.js +1 -1
  58. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
  59. package/dist/src/sourcemaps/tools/sentry-cli.js +19 -16
  60. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  61. package/dist/src/sourcemaps/tools/vite.d.ts +2 -1
  62. package/dist/src/sourcemaps/tools/vite.js +123 -111
  63. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  64. package/dist/src/sourcemaps/tools/webpack.d.ts +6 -1
  65. package/dist/src/sourcemaps/tools/webpack.js +290 -25
  66. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  67. package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
  68. package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
  69. package/dist/src/sveltekit/sdk-setup.js +5 -5
  70. package/dist/src/sveltekit/sdk-setup.js.map +1 -1
  71. package/dist/src/sveltekit/sveltekit-wizard.js +34 -44
  72. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  73. package/dist/src/telemetry.js +1 -0
  74. package/dist/src/telemetry.js.map +1 -1
  75. package/dist/src/utils/ast-utils.d.ts +9 -5
  76. package/dist/src/utils/ast-utils.js +26 -11
  77. package/dist/src/utils/ast-utils.js.map +1 -1
  78. package/dist/src/utils/clack-utils.d.ts +74 -28
  79. package/dist/src/utils/clack-utils.js +427 -264
  80. package/dist/src/utils/clack-utils.js.map +1 -1
  81. package/dist/src/utils/package-manager.d.ts +10 -0
  82. package/dist/{lib/Helper/PackageManager.js → src/utils/package-manager.js} +42 -74
  83. package/dist/src/utils/package-manager.js.map +1 -0
  84. package/dist/src/utils/release-registry.d.ts +1 -0
  85. package/dist/src/utils/release-registry.js +68 -0
  86. package/dist/src/utils/release-registry.js.map +1 -0
  87. package/dist/src/utils/sentrycli-utils.d.ts +4 -0
  88. package/dist/src/utils/sentrycli-utils.js +41 -0
  89. package/dist/src/utils/sentrycli-utils.js.map +1 -0
  90. package/dist/test/android/code-tools.test.d.ts +1 -0
  91. package/dist/test/android/code-tools.test.js +34 -0
  92. package/dist/test/android/code-tools.test.js.map +1 -0
  93. package/dist/test/sourcemaps/tools/vite.test.d.ts +1 -0
  94. package/dist/test/sourcemaps/tools/vite.test.js +132 -0
  95. package/dist/test/sourcemaps/tools/vite.test.js.map +1 -0
  96. package/dist/test/sourcemaps/tools/webpack.test.d.ts +1 -0
  97. package/dist/test/sourcemaps/tools/webpack.test.js +179 -0
  98. package/dist/test/sourcemaps/tools/webpack.test.js.map +1 -0
  99. package/dist/test/utils/ast-utils.test.js +42 -7
  100. package/dist/test/utils/ast-utils.test.js.map +1 -1
  101. package/dist/test/utils/clack-utils.test.d.ts +1 -0
  102. package/dist/test/utils/clack-utils.test.js +200 -0
  103. package/dist/test/utils/clack-utils.test.js.map +1 -0
  104. package/lib/Constants.ts +5 -0
  105. package/lib/Steps/ChooseIntegration.ts +7 -3
  106. package/lib/Steps/Integrations/Android.ts +23 -0
  107. package/lib/Steps/Integrations/ReactNative.ts +9 -3
  108. package/lib/Steps/PromptForParameters.ts +48 -3
  109. package/lib/Steps/SentryProjectSelector.ts +3 -1
  110. package/package.json +4 -3
  111. package/src/android/android-wizard.ts +204 -0
  112. package/src/android/code-tools.ts +170 -0
  113. package/src/android/gradle.ts +250 -0
  114. package/src/android/manifest.ts +180 -0
  115. package/src/android/templates.ts +88 -0
  116. package/src/apple/apple-wizard.ts +113 -35
  117. package/src/apple/cocoapod.ts +6 -3
  118. package/src/apple/code-tools.ts +46 -18
  119. package/src/apple/fastlane.ts +6 -12
  120. package/src/apple/templates.ts +2 -8
  121. package/src/apple/xcode-manager.ts +167 -25
  122. package/src/nextjs/nextjs-wizard.ts +72 -8
  123. package/src/nextjs/templates.ts +16 -2
  124. package/src/remix/remix-wizard.ts +10 -15
  125. package/src/sourcemaps/sourcemaps-wizard.ts +19 -5
  126. package/src/sourcemaps/tools/nextjs.ts +2 -2
  127. package/src/sourcemaps/tools/sentry-cli.ts +8 -7
  128. package/src/sourcemaps/tools/vite.ts +143 -79
  129. package/src/sourcemaps/tools/webpack.ts +369 -30
  130. package/src/sourcemaps/utils/detect-tool.ts +2 -1
  131. package/src/sveltekit/sdk-setup.ts +10 -6
  132. package/src/sveltekit/sveltekit-wizard.ts +5 -14
  133. package/src/telemetry.ts +2 -0
  134. package/src/utils/ast-utils.ts +29 -11
  135. package/src/utils/clack-utils.ts +485 -283
  136. package/src/utils/package-manager.ts +61 -0
  137. package/src/utils/release-registry.ts +19 -0
  138. package/src/utils/sentrycli-utils.ts +22 -0
  139. package/test/android/code-tools.test.ts +49 -0
  140. package/test/sourcemaps/tools/vite.test.ts +149 -0
  141. package/test/sourcemaps/tools/webpack.test.ts +303 -0
  142. package/test/utils/ast-utils.test.ts +28 -9
  143. package/test/utils/clack-utils.test.ts +142 -0
  144. package/dist/lib/Helper/PackageManager.d.ts +0 -22
  145. package/dist/lib/Helper/PackageManager.js.map +0 -1
  146. package/dist/src/utils/vendor/clack-custom-select.d.ts +0 -21
  147. package/dist/src/utils/vendor/clack-custom-select.js +0 -137
  148. package/dist/src/utils/vendor/clack-custom-select.js.map +0 -1
  149. package/lib/Helper/PackageManager.ts +0 -59
  150. package/src/utils/vendor/clack-custom-select.ts +0 -160
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sourceContextKts = exports.sourceContext = exports.testErrorSnippetKt = exports.testErrorSnippet = exports.sentryImportKt = exports.sentryImport = exports.manifest = exports.pluginKts = exports.plugin = exports.pluginsBlockKts = exports.pluginsBlock = void 0;
4
+ var pluginsBlock = function (version) {
5
+ if (version === void 0) { version = '3.12.0'; }
6
+ return "\nplugins {\n id 'io.sentry.android.gradle' version '".concat(version, "'\n}\n\n");
7
+ };
8
+ exports.pluginsBlock = pluginsBlock;
9
+ var pluginsBlockKts = function (version) {
10
+ if (version === void 0) { version = '3.12.0'; }
11
+ return "\nplugins {\n id(\"io.sentry.android.gradle\") version \"".concat(version, "\"\n}\n\n");
12
+ };
13
+ exports.pluginsBlockKts = pluginsBlockKts;
14
+ var plugin = function (version) {
15
+ if (version === void 0) { version = '3.12.0'; }
16
+ return "\n id 'io.sentry.android.gradle' version '".concat(version, "'\n");
17
+ };
18
+ exports.plugin = plugin;
19
+ var pluginKts = function (version) {
20
+ if (version === void 0) { version = '3.12.0'; }
21
+ return "\n id(\"io.sentry.android.gradle\") version \"".concat(version, "\"\n");
22
+ };
23
+ exports.pluginKts = pluginKts;
24
+ var manifest = function (dsn) { return "\n <!-- Required: set your sentry.io project identifier (DSN) -->\n <meta-data android:name=\"io.sentry.dsn\" android:value=\"".concat(dsn, "\" />\n\n <!-- enable automatic breadcrumbs for user interactions (clicks, swipes, scrolls) -->\n <meta-data android:name=\"io.sentry.traces.user-interaction.enable\" android:value=\"true\" />\n <!-- enable screenshot for crashes (could contain sensitive/PII data) -->\n <meta-data android:name=\"io.sentry.attach-screenshot\" android:value=\"true\" />\n <!-- enable view hierarchy for crashes -->\n <meta-data android:name=\"io.sentry.attach-view-hierarchy\" android:value=\"true\" />\n\n <!-- enable the performance API by setting a sample-rate, adjust in production env -->\n <meta-data android:name=\"io.sentry.traces.sample-rate\" android:value=\"1.0\" />\n <!-- enable profiling when starting transactions, adjust in production env -->\n <meta-data android:name=\"io.sentry.traces.profiling.sample-rate\" android:value=\"1.0\" />\n"); };
25
+ exports.manifest = manifest;
26
+ exports.sentryImport = "import io.sentry.Sentry;\n";
27
+ exports.sentryImportKt = "import io.sentry.Sentry\n";
28
+ exports.testErrorSnippet = "\n // waiting for view to draw to better represent a captured error with a screenshot\n findViewById(android.R.id.content).getViewTreeObserver().addOnGlobalLayoutListener(() -> {\n try {\n throw new Exception(\"This app uses Sentry! :)\");\n } catch (Exception e) {\n Sentry.captureException(e);\n }\n });\n";
29
+ exports.testErrorSnippetKt = "\n // waiting for view to draw to better represent a captured error with a screenshot\n findViewById<android.view.View>(android.R.id.content).viewTreeObserver.addOnGlobalLayoutListener {\n try {\n throw Exception(\"This app uses Sentry! :)\")\n } catch (e: Exception) {\n Sentry.captureException(e)\n }\n }\n";
30
+ var sourceContext = function (orgSlug, projectSlug) { return "\n\nsentry {\n org = \"".concat(orgSlug, "\"\n projectName = \"").concat(projectSlug, "\"\n\n // this will upload your source code to Sentry to show it as part of the stack traces\n // disable if you don't want to expose your sources\n includeSourceContext = true\n}\n"); };
31
+ exports.sourceContext = sourceContext;
32
+ var sourceContextKts = function (orgSlug, projectSlug) { return "\n\nsentry {\n org.set(\"".concat(orgSlug, "\")\n projectName.set(\"").concat(projectSlug, "\")\n\n // this will upload your source code to Sentry to show it as part of the stack traces\n // disable if you don't want to expose your sources\n includeSourceContext.set(true)\n}\n"); };
33
+ exports.sourceContextKts = sourceContextKts;
34
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/android/templates.ts"],"names":[],"mappings":";;;AAAO,IAAM,YAAY,GAAG,UAAC,OAAkB;IAAlB,wBAAA,EAAA,kBAAkB;IAAK,OAAA,kEAEP,OAAO,aAGnD;AALmD,CAKnD,CAAC;AALW,QAAA,YAAY,gBAKvB;AAEK,IAAM,eAAe,GAAG,UAAC,OAAkB;IAAlB,wBAAA,EAAA,kBAAkB;IAAK,OAAA,sEAET,OAAO,cAGpD;AALsD,CAKtD,CAAC;AALW,QAAA,eAAe,mBAK1B;AAEK,IAAM,MAAM,GAAG,UAAC,OAAkB;IAAlB,wBAAA,EAAA,kBAAkB;IAAK,OAAA,uDACD,OAAO,QACnD;AAF6C,CAE7C,CAAC;AAFW,QAAA,MAAM,UAEjB;AAEK,IAAM,SAAS,GAAG,UAAC,OAAkB;IAAlB,wBAAA,EAAA,kBAAkB;IAAK,OAAA,2DACH,OAAO,SACpD;AAFgD,CAEhD,CAAC;AAFW,QAAA,SAAS,aAEpB;AAEK,IAAM,QAAQ,GAAG,UAAC,GAAW,IAAK,OAAA,8IAEoB,GAAG,w2BAa/D,EAfwC,CAexC,CAAC;AAfW,QAAA,QAAQ,YAenB;AAEW,QAAA,YAAY,GAAG,4BAA4B,CAAC;AAE5C,QAAA,cAAc,GAAG,2BAA2B,CAAC;AAE7C,QAAA,gBAAgB,GAAG,2VAS/B,CAAC;AAEW,QAAA,kBAAkB,GAAG,4VASjC,CAAC;AAEK,IAAM,aAAa,GAAG,UAAC,OAAe,EAAE,WAAmB,IAAK,OAAA,oCAG1D,OAAO,qCACC,WAAW,mMAM/B,EAVsE,CAUtE,CAAC;AAVW,QAAA,aAAa,iBAUxB;AAEK,IAAM,gBAAgB,GAAG,UAAC,OAAe,EAAE,WAAmB,IAAK,OAAA,sCAG3D,OAAO,wCACC,WAAW,uMAMjC,EAVyE,CAUzE,CAAC;AAVW,QAAA,gBAAgB,oBAU3B","sourcesContent":["export const pluginsBlock = (version = '3.12.0') => `\nplugins {\n id 'io.sentry.android.gradle' version '${version}'\n}\n\n`;\n\nexport const pluginsBlockKts = (version = '3.12.0') => `\nplugins {\n id(\"io.sentry.android.gradle\") version \"${version}\"\n}\n\n`;\n\nexport const plugin = (version = '3.12.0') => `\n id 'io.sentry.android.gradle' version '${version}'\n`;\n\nexport const pluginKts = (version = '3.12.0') => `\n id(\"io.sentry.android.gradle\") version \"${version}\"\n`;\n\nexport const manifest = (dsn: string) => `\n <!-- Required: set your sentry.io project identifier (DSN) -->\n <meta-data android:name=\"io.sentry.dsn\" android:value=\"${dsn}\" />\n\n <!-- enable automatic breadcrumbs for user interactions (clicks, swipes, scrolls) -->\n <meta-data android:name=\"io.sentry.traces.user-interaction.enable\" android:value=\"true\" />\n <!-- enable screenshot for crashes (could contain sensitive/PII data) -->\n <meta-data android:name=\"io.sentry.attach-screenshot\" android:value=\"true\" />\n <!-- enable view hierarchy for crashes -->\n <meta-data android:name=\"io.sentry.attach-view-hierarchy\" android:value=\"true\" />\n\n <!-- enable the performance API by setting a sample-rate, adjust in production env -->\n <meta-data android:name=\"io.sentry.traces.sample-rate\" android:value=\"1.0\" />\n <!-- enable profiling when starting transactions, adjust in production env -->\n <meta-data android:name=\"io.sentry.traces.profiling.sample-rate\" android:value=\"1.0\" />\n`;\n\nexport const sentryImport = `import io.sentry.Sentry;\\n`;\n\nexport const sentryImportKt = `import io.sentry.Sentry\\n`;\n\nexport const testErrorSnippet = `\n // waiting for view to draw to better represent a captured error with a screenshot\n findViewById(android.R.id.content).getViewTreeObserver().addOnGlobalLayoutListener(() -> {\n try {\n throw new Exception(\"This app uses Sentry! :)\");\n } catch (Exception e) {\n Sentry.captureException(e);\n }\n });\n`;\n\nexport const testErrorSnippetKt = `\n // waiting for view to draw to better represent a captured error with a screenshot\n findViewById<android.view.View>(android.R.id.content).viewTreeObserver.addOnGlobalLayoutListener {\n try {\n throw Exception(\"This app uses Sentry! :)\")\n } catch (e: Exception) {\n Sentry.captureException(e)\n }\n }\n`;\n\nexport const sourceContext = (orgSlug: string, projectSlug: string) => `\n\nsentry {\n org = \"${orgSlug}\"\n projectName = \"${projectSlug}\"\n\n // this will upload your source code to Sentry to show it as part of the stack traces\n // disable if you don't want to expose your sources\n includeSourceContext = true\n}\n`;\n\nexport const sourceContextKts = (orgSlug: string, projectSlug: string) => `\n\nsentry {\n org.set(\"${orgSlug}\")\n projectName.set(\"${projectSlug}\")\n\n // this will upload your source code to Sentry to show it as part of the stack traces\n // disable if you don't want to expose your sources\n includeSourceContext.set(true)\n}\n`;\n"]}
@@ -72,9 +72,10 @@ exports.runAppleWizard = void 0;
72
72
  var prompts_1 = __importDefault(require("@clack/prompts"));
73
73
  var fs = __importStar(require("fs"));
74
74
  var path = __importStar(require("path"));
75
- var xcManager = __importStar(require("./xcode-manager"));
75
+ var xcode_manager_1 = require("./xcode-manager");
76
76
  var codeTools = __importStar(require("./code-tools"));
77
77
  var bash = __importStar(require("../utils/bash"));
78
+ var SentryUtils = __importStar(require("../utils/sentrycli-utils"));
78
79
  var Sentry = __importStar(require("@sentry/node"));
79
80
  var telemetry_1 = require("../telemetry");
80
81
  var cocoapod = __importStar(require("./cocoapod"));
@@ -95,129 +96,187 @@ function runAppleWizard(options) {
95
96
  exports.runAppleWizard = runAppleWizard;
96
97
  function runAppleWizardWithTelementry(options) {
97
98
  return __awaiter(this, void 0, void 0, function () {
98
- var hasCli, projectDir, xcodeProjFiles, xcodeProjFile, pbxproj, _a, project, apiKey, hasCocoa, podAdded, projSource, codeAdded, addLane;
99
- return __generator(this, function (_b) {
100
- switch (_b.label) {
99
+ var hasCli, projectDir, xcodeProjFiles, xcodeProjFile, pbxproj, _a, project, apiKey, xcProject, availableTargets, target, _b, hasCocoa, pm, podAdded, codeAdded, addLane, added;
100
+ return __generator(this, function (_c) {
101
+ switch (_c.label) {
101
102
  case 0:
102
103
  (0, clack_utils_1.printWelcome)({
103
104
  wizardName: 'Sentry Apple Wizard',
104
105
  promoCode: options.promoCode,
105
106
  });
107
+ return [4 /*yield*/, (0, clack_utils_1.confirmContinueEvenThoughNoGitRepo)()];
108
+ case 1:
109
+ _c.sent();
106
110
  hasCli = bash.hasSentryCLI();
107
111
  Sentry.setTag('has-cli', hasCli);
108
- if (!!hasCli) return [3 /*break*/, 4];
112
+ if (!!hasCli) return [3 /*break*/, 5];
109
113
  return [4 /*yield*/, (0, telemetry_1.traceStep)('Ask for SentryCLI', function () { return (0, clack_utils_1.askToInstallSentryCLI)(); })];
110
- case 1:
111
- if (!!(_b.sent())) return [3 /*break*/, 2];
114
+ case 2:
115
+ if (!!(_c.sent())) return [3 /*break*/, 3];
112
116
  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/");
113
117
  Sentry.setTag('CLI-Installed', false);
114
- return [3 /*break*/, 4];
115
- case 2: return [4 /*yield*/, bash.installSentryCLI()];
116
- case 3:
117
- _b.sent();
118
- Sentry.setTag('CLI-Installed', true);
119
- _b.label = 4;
118
+ return [3 /*break*/, 5];
119
+ case 3: return [4 /*yield*/, bash.installSentryCLI()];
120
120
  case 4:
121
+ _c.sent();
122
+ Sentry.setTag('CLI-Installed', true);
123
+ _c.label = 5;
124
+ case 5:
121
125
  projectDir = process.cwd();
122
- xcodeProjFiles = findFilesWithExtension(projectDir, '.xcodeproj');
123
- if (!(!xcodeProjFiles || xcodeProjFiles.length === 0)) return [3 /*break*/, 6];
126
+ xcodeProjFiles = searchXcodeProject(projectDir);
127
+ if (!(!xcodeProjFiles || xcodeProjFiles.length === 0)) return [3 /*break*/, 7];
124
128
  prompts_1.default.log.error('No Xcode project found. Please run this command from the root of your project.');
125
129
  return [4 /*yield*/, (0, clack_utils_1.abort)()];
126
- case 5:
127
- _b.sent();
128
- return [2 /*return*/];
129
130
  case 6:
130
- if (!(xcodeProjFiles.length === 1)) return [3 /*break*/, 7];
131
+ _c.sent();
132
+ return [2 /*return*/];
133
+ case 7:
134
+ if (!(xcodeProjFiles.length === 1)) return [3 /*break*/, 8];
131
135
  xcodeProjFile = xcodeProjFiles[0];
132
136
  Sentry.setTag('multiple-projects', false);
133
- return [3 /*break*/, 9];
134
- case 7:
137
+ return [3 /*break*/, 10];
138
+ case 8:
135
139
  Sentry.setTag('multiple-projects', true);
136
140
  return [4 /*yield*/, (0, telemetry_1.traceStep)('Choose Xcode project', function () {
137
141
  return (0, clack_utils_1.askForItemSelection)(xcodeProjFiles, 'Which project do you want to add Sentry to?');
138
142
  })];
139
- case 8:
140
- xcodeProjFile = (_b.sent()).value;
141
- _b.label = 9;
142
143
  case 9:
144
+ xcodeProjFile = (_c.sent()).value;
145
+ _c.label = 10;
146
+ case 10:
143
147
  pbxproj = path.join(projectDir, xcodeProjFile, 'project.pbxproj');
144
- if (!!fs.existsSync(pbxproj)) return [3 /*break*/, 11];
145
- prompts_1.default.log.error("No pbxproj found at ".concat(pbxproj));
148
+ if (!!fs.existsSync(pbxproj)) return [3 /*break*/, 12];
149
+ prompts_1.default.log.error("No pbxproj found at ".concat(xcodeProjFile));
146
150
  return [4 /*yield*/, (0, clack_utils_1.abort)()];
147
- case 10:
148
- _b.sent();
151
+ case 11:
152
+ _c.sent();
149
153
  return [2 /*return*/];
150
- case 11: return [4 /*yield*/, getSentryProjectAndApiKey(options.promoCode, options.url)];
151
- case 12:
152
- _a = _b.sent(), project = _a.project, apiKey = _a.apiKey;
154
+ case 12: return [4 /*yield*/, getSentryProjectAndApiKey(options)];
155
+ case 13:
156
+ _a = _c.sent(), project = _a.project, apiKey = _a.apiKey;
157
+ xcProject = new xcode_manager_1.XcodeProject(pbxproj);
158
+ availableTargets = xcProject.getAllTargets();
159
+ if (!(availableTargets.length == 0)) return [3 /*break*/, 15];
160
+ prompts_1.default.log.error("No suttable target found in ".concat(xcodeProjFile));
161
+ return [4 /*yield*/, (0, clack_utils_1.abort)()];
162
+ case 14:
163
+ _c.sent();
164
+ return [2 /*return*/];
165
+ case 15:
166
+ if (!(availableTargets.length == 1)) return [3 /*break*/, 16];
167
+ _b = availableTargets[0];
168
+ return [3 /*break*/, 18];
169
+ case 16: return [4 /*yield*/, (0, telemetry_1.traceStep)('Choose target', function () {
170
+ return (0, clack_utils_1.askForItemSelection)(availableTargets, 'Which target do you want to add Sentry to?');
171
+ })];
172
+ case 17:
173
+ _b = (_c.sent()).value;
174
+ _c.label = 18;
175
+ case 18:
176
+ target = _b;
177
+ SentryUtils.createSentryCLIRC(projectDir, { auth_token: apiKey.token });
178
+ prompts_1.default.log.info('We created a ".sentryclirc" file in your project directory in order to provide an auth token for Sentry CLI.\nIt was also added to your ".gitignore" file.\nAt your CI enviroment, you can set the SENTRY_AUTH_TOKEN environment variable instead. See https://docs.sentry.io/cli/configuration/#auth-token for more information.');
153
179
  hasCocoa = cocoapod.usesCocoaPod(projectDir);
154
- if (!hasCocoa) return [3 /*break*/, 14];
180
+ if (!hasCocoa) return [3 /*break*/, 21];
181
+ return [4 /*yield*/, (0, telemetry_1.traceStep)('Choose a package manager', function () {
182
+ return (0, clack_utils_1.askForItemSelection)(['Swift Package Manager', 'CocoaPods'], 'Which package manager would you like to use to add Sentry?');
183
+ })];
184
+ case 19:
185
+ pm = (_c.sent()).value;
186
+ hasCocoa = pm === 'CocoaPods';
187
+ if (!hasCocoa) return [3 /*break*/, 21];
155
188
  return [4 /*yield*/, (0, telemetry_1.traceStep)('Add CocoaPods reference', function () {
156
189
  return cocoapod.addCocoaPods(projectDir);
157
190
  })];
158
- case 13:
159
- podAdded = _b.sent();
191
+ case 20:
192
+ podAdded = _c.sent();
160
193
  if (!podAdded) {
161
194
  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");
162
195
  }
163
- _b.label = 14;
164
- case 14:
196
+ _c.label = 21;
197
+ case 21:
165
198
  (0, telemetry_1.traceStep)('Update Xcode project', function () {
166
- xcManager.updateXcodeProject(pbxproj, project, apiKey, !hasCocoa, true);
199
+ xcProject.updateXcodeProject(project, target, apiKey, !hasCocoa, true);
167
200
  });
168
201
  Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');
169
- projSource = path.join(projectDir, xcodeProjFile.replace('.xcodeproj', ''));
170
202
  codeAdded = (0, telemetry_1.traceStep)('Add code snippet', function () {
171
- return codeTools.addCodeSnippetToProject(projSource, project.keys[0].dsn.public);
203
+ var files = xcProject.filesForTarget(target);
204
+ if (files === undefined || files.length == 0)
205
+ return false;
206
+ return codeTools.addCodeSnippetToProject(projectDir, files, project.keys[0].dsn.public);
172
207
  });
173
208
  if (!codeAdded) {
174
209
  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');
175
210
  return [2 /*return*/];
176
211
  }
177
- if (!fastlane.fastFile(projectDir)) return [3 /*break*/, 17];
212
+ if (!fastlane.fastFile(projectDir)) return [3 /*break*/, 24];
178
213
  return [4 /*yield*/, prompts_1.default.confirm({
179
214
  message: 'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',
180
215
  })];
181
- case 15:
182
- addLane = _b.sent();
183
- if (!addLane) return [3 /*break*/, 17];
216
+ case 22:
217
+ addLane = _c.sent();
218
+ if (!addLane) return [3 /*break*/, 24];
184
219
  return [4 /*yield*/, (0, telemetry_1.traceStep)('Configure fastlane', function () {
185
- return fastlane.addSentryToFastlane(projectDir, project.organization.slug, project.slug, apiKey.token);
220
+ return fastlane.addSentryToFastlane(projectDir, project.organization.slug, project.slug);
186
221
  })];
187
- case 16:
188
- _b.sent();
189
- _b.label = 17;
190
- case 17:
191
- prompts_1.default.log.success('Sentry was successfully added to your project!');
222
+ case 23:
223
+ added = _c.sent();
224
+ if (added) {
225
+ 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.');
226
+ }
227
+ else {
228
+ 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');
229
+ }
230
+ _c.label = 24;
231
+ case 24:
232
+ 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.');
192
233
  return [2 /*return*/];
193
234
  }
194
235
  });
195
236
  });
196
237
  }
197
238
  //Prompt for Sentry project and API key
198
- function getSentryProjectAndApiKey(promoCode, url) {
239
+ function getSentryProjectAndApiKey(options) {
199
240
  return __awaiter(this, void 0, void 0, function () {
200
- var sentryUrl, _a, projects, apiKeys, selectedProject;
241
+ var _a, selectedProject, authToken;
201
242
  return __generator(this, function (_b) {
202
243
  switch (_b.label) {
203
- case 0: return [4 /*yield*/, (0, clack_utils_1.askForSelfHosted)(url)];
244
+ case 0: return [4 /*yield*/, (0, clack_utils_1.getOrAskForProjectData)(options)];
204
245
  case 1:
205
- sentryUrl = (_b.sent()).url;
206
- return [4 /*yield*/, (0, clack_utils_1.askForWizardLogin)({
207
- promoCode: promoCode,
208
- url: sentryUrl,
209
- platform: 'apple-ios',
210
- })];
211
- case 2:
212
- _a = _b.sent(), projects = _a.projects, apiKeys = _a.apiKeys;
213
- return [4 /*yield*/, (0, clack_utils_1.askForProjectSelection)(projects)];
214
- case 3:
215
- selectedProject = _b.sent();
216
- return [2 /*return*/, { project: selectedProject, apiKey: apiKeys }];
246
+ _a = _b.sent(), selectedProject = _a.selectedProject, authToken = _a.authToken;
247
+ return [2 /*return*/, { project: selectedProject, apiKey: { token: authToken } }];
217
248
  }
218
249
  });
219
250
  });
220
251
  }
252
+ function searchXcodeProject(at) {
253
+ var projs = findFilesWithExtension(at, '.xcodeproj');
254
+ if (projs.length > 0) {
255
+ return projs;
256
+ }
257
+ var workspace = findFilesWithExtension(at, '.xcworkspace');
258
+ if (workspace.length == 0) {
259
+ return [];
260
+ }
261
+ var xsworkspacedata = path.join(at, workspace[0], 'contents.xcworkspacedata');
262
+ if (!fs.existsSync(xsworkspacedata)) {
263
+ return [];
264
+ }
265
+ var groupRegex = /location *= *"group:([^"]+)"/gim;
266
+ var content = fs.readFileSync(xsworkspacedata, 'utf8');
267
+ var matches = groupRegex.exec(content);
268
+ while (matches) {
269
+ var group = matches[1];
270
+ var groupPath = path.join(at, group);
271
+ if (!group.endsWith('Pods.xcodeproj') &&
272
+ group.endsWith('.xcodeproj') &&
273
+ fs.existsSync(groupPath)) {
274
+ projs.push(group);
275
+ }
276
+ matches = groupRegex.exec(content);
277
+ }
278
+ return projs;
279
+ }
221
280
  //find files with the given extension
222
281
  function findFilesWithExtension(dir, extension) {
223
282
  var files = fs.readdirSync(dir);
@@ -1 +1 @@
1
- {"version":3,"file":"apple-wizard.js","sourceRoot":"","sources":["../../../src/apple/apple-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unused-vars */\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as xcManager from './xcode-manager';\nimport * as codeTools from './code-tools';\nimport * as bash from '../utils/bash';\nimport { SentryProjectData, WizardOptions } from '../utils/types';\nimport * as Sentry from '@sentry/node';\nimport { traceStep, withTelemetry } from '../telemetry';\nimport * as cocoapod from './cocoapod';\nimport * as fastlane from './fastlane';\n\nconst xcode = require('xcode');\n/* eslint-enable @typescript-eslint/no-unused-vars */\n\nimport {\n askForProjectSelection,\n askForSelfHosted,\n askForWizardLogin,\n askToInstallSentryCLI,\n printWelcome,\n abort,\n askForItemSelection,\n} from '../utils/clack-utils';\n\nexport async function runAppleWizard(options: WizardOptions): Promise<void> {\n return withTelemetry(\n {\n enabled: options.telemetryEnabled,\n integration: 'ios',\n },\n () => runAppleWizardWithTelementry(options),\n );\n}\n\nasync function runAppleWizardWithTelementry(\n options: WizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry Apple Wizard',\n promoCode: options.promoCode,\n });\n\n const hasCli = bash.hasSentryCLI();\n Sentry.setTag('has-cli', hasCli);\n if (!hasCli) {\n if (\n !(await traceStep('Ask for SentryCLI', () => askToInstallSentryCLI()))\n ) {\n clack.log.warn(\n \"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/\",\n );\n Sentry.setTag('CLI-Installed', false);\n } else {\n await bash.installSentryCLI();\n Sentry.setTag('CLI-Installed', true);\n }\n }\n\n const projectDir = process.cwd();\n const xcodeProjFiles = findFilesWithExtension(projectDir, '.xcodeproj');\n\n if (!xcodeProjFiles || xcodeProjFiles.length === 0) {\n clack.log.error(\n 'No Xcode project found. Please run this command from the root of your project.',\n );\n await abort();\n return;\n }\n\n let xcodeProjFile;\n\n if (xcodeProjFiles.length === 1) {\n xcodeProjFile = xcodeProjFiles[0];\n Sentry.setTag('multiple-projects', false);\n } else {\n Sentry.setTag('multiple-projects', true);\n xcodeProjFile = (\n await traceStep('Choose Xcode project', () =>\n askForItemSelection(\n xcodeProjFiles,\n 'Which project do you want to add Sentry to?',\n ),\n )\n ).value;\n }\n\n const pbxproj = path.join(projectDir, xcodeProjFile, 'project.pbxproj');\n if (!fs.existsSync(pbxproj)) {\n clack.log.error(`No pbxproj found at ${pbxproj}`);\n await abort();\n return;\n }\n\n const { project, apiKey } = await getSentryProjectAndApiKey(\n options.promoCode,\n options.url,\n );\n\n const hasCocoa = cocoapod.usesCocoaPod(projectDir);\n\n if (hasCocoa) {\n const podAdded = await traceStep('Add CocoaPods reference', () =>\n cocoapod.addCocoaPods(projectDir),\n );\n if (!podAdded) {\n clack.log.warn(\n \"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\",\n );\n }\n }\n\n traceStep('Update Xcode project', () => {\n xcManager.updateXcodeProject(pbxproj, project, apiKey, !hasCocoa, true);\n });\n\n Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');\n const projSource = path.join(\n projectDir,\n xcodeProjFile.replace('.xcodeproj', ''),\n );\n const codeAdded = traceStep('Add code snippet', () => {\n return codeTools.addCodeSnippetToProject(\n projSource,\n project.keys[0].dsn.public,\n );\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 snipped manually by following the docs: https://docs.sentry.io/platforms/apple/guides/ios/#configure',\n );\n return;\n }\n\n if (fastlane.fastFile(projectDir)) {\n const addLane = await clack.confirm({\n message:\n 'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',\n });\n if (addLane) {\n await traceStep('Configure fastlane', () =>\n fastlane.addSentryToFastlane(\n projectDir,\n project.organization.slug,\n project.slug,\n apiKey.token,\n ),\n );\n }\n }\n\n clack.log.success('Sentry was successfully added to your project!');\n}\n\n//Prompt for Sentry project and API key\nasync function getSentryProjectAndApiKey(\n promoCode?: string,\n url?: string,\n): Promise<{ project: SentryProjectData; apiKey: { token: string } }> {\n const { url: sentryUrl } = await askForSelfHosted(url);\n\n const { projects, apiKeys } = await askForWizardLogin({\n promoCode: promoCode,\n url: sentryUrl,\n platform: 'apple-ios',\n });\n\n const selectedProject = await askForProjectSelection(projects);\n return { project: selectedProject, apiKey: apiKeys };\n}\n\n//find files with the given extension\nfunction findFilesWithExtension(dir: string, extension: string): string[] {\n const files = fs.readdirSync(dir);\n return files.filter((file) => file.endsWith(extension));\n}\n"]}
1
+ {"version":3,"file":"apple-wizard.js","sourceRoot":"","sources":["../../../src/apple/apple-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unused-vars */\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { XcodeProject } from './xcode-manager';\nimport * as codeTools from './code-tools';\nimport * as bash from '../utils/bash';\nimport * as SentryUtils from '../utils/sentrycli-utils';\nimport { SentryProjectData, WizardOptions } from '../utils/types';\nimport * as Sentry from '@sentry/node';\nimport { traceStep, withTelemetry } from '../telemetry';\nimport * as cocoapod from './cocoapod';\nimport * as fastlane from './fastlane';\n\nconst xcode = require('xcode');\n/* eslint-enable @typescript-eslint/no-unused-vars */\n\nimport {\n askToInstallSentryCLI,\n printWelcome,\n abort,\n askForItemSelection,\n confirmContinueEvenThoughNoGitRepo,\n getOrAskForProjectData,\n} from '../utils/clack-utils';\n\nexport async function runAppleWizard(options: WizardOptions): Promise<void> {\n return withTelemetry(\n {\n enabled: options.telemetryEnabled,\n integration: 'ios',\n },\n () => runAppleWizardWithTelementry(options),\n );\n}\n\nasync function runAppleWizardWithTelementry(\n options: WizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry Apple Wizard',\n promoCode: options.promoCode,\n });\n\n await confirmContinueEvenThoughNoGitRepo();\n\n const hasCli = bash.hasSentryCLI();\n Sentry.setTag('has-cli', hasCli);\n if (!hasCli) {\n if (\n !(await traceStep('Ask for SentryCLI', () => askToInstallSentryCLI()))\n ) {\n clack.log.warn(\n \"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/\",\n );\n Sentry.setTag('CLI-Installed', false);\n } else {\n await bash.installSentryCLI();\n Sentry.setTag('CLI-Installed', true);\n }\n }\n\n const projectDir = process.cwd();\n const xcodeProjFiles = searchXcodeProject(projectDir);\n\n if (!xcodeProjFiles || xcodeProjFiles.length === 0) {\n clack.log.error(\n 'No Xcode project found. Please run this command from the root of your project.',\n );\n await abort();\n return;\n }\n\n let xcodeProjFile;\n\n if (xcodeProjFiles.length === 1) {\n xcodeProjFile = xcodeProjFiles[0];\n Sentry.setTag('multiple-projects', false);\n } else {\n Sentry.setTag('multiple-projects', true);\n xcodeProjFile = (\n await traceStep('Choose Xcode project', () =>\n askForItemSelection(\n xcodeProjFiles,\n 'Which project do you want to add Sentry to?',\n ),\n )\n ).value;\n }\n\n const pbxproj = path.join(projectDir, xcodeProjFile, 'project.pbxproj');\n\n if (!fs.existsSync(pbxproj)) {\n clack.log.error(`No pbxproj found at ${xcodeProjFile}`);\n await abort();\n return;\n }\n\n const { project, apiKey } = await getSentryProjectAndApiKey(options);\n\n const xcProject = new XcodeProject(pbxproj);\n\n const availableTargets = xcProject.getAllTargets();\n\n if (availableTargets.length == 0) {\n clack.log.error(`No suttable target found in ${xcodeProjFile}`);\n await abort();\n return;\n }\n\n const target =\n availableTargets.length == 1\n ? availableTargets[0]\n : (\n await traceStep('Choose target', () =>\n askForItemSelection(\n availableTargets,\n 'Which target do you want to add Sentry to?',\n ),\n )\n ).value;\n\n SentryUtils.createSentryCLIRC(projectDir, { auth_token: apiKey.token });\n clack.log.info(\n 'We created a \".sentryclirc\" file in your project directory in order to provide an auth token for Sentry CLI.\\nIt was also added to your \".gitignore\" file.\\nAt your CI enviroment, you can set the SENTRY_AUTH_TOKEN environment variable instead. See https://docs.sentry.io/cli/configuration/#auth-token for more information.',\n );\n\n let hasCocoa = cocoapod.usesCocoaPod(projectDir);\n\n if (hasCocoa) {\n const pm = (\n await traceStep('Choose a package manager', () =>\n askForItemSelection(\n ['Swift Package Manager', 'CocoaPods'],\n 'Which package manager would you like to use to add Sentry?',\n ),\n )\n ).value;\n\n hasCocoa = pm === 'CocoaPods';\n if (hasCocoa) {\n const podAdded = await traceStep('Add CocoaPods reference', () =>\n cocoapod.addCocoaPods(projectDir),\n );\n if (!podAdded) {\n clack.log.warn(\n \"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\",\n );\n }\n }\n }\n\n traceStep('Update Xcode project', () => {\n xcProject.updateXcodeProject(project, target, apiKey, !hasCocoa, true);\n });\n\n Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');\n const codeAdded = traceStep('Add code snippet', () => {\n const files = xcProject.filesForTarget(target);\n if (files === undefined || files.length == 0) return false;\n\n return codeTools.addCodeSnippetToProject(\n projectDir,\n files,\n project.keys[0].dsn.public,\n );\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 snipped manually by following the docs: https://docs.sentry.io/platforms/apple/guides/ios/#configure',\n );\n return;\n }\n\n if (fastlane.fastFile(projectDir)) {\n const addLane = await clack.confirm({\n message:\n 'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',\n });\n if (addLane) {\n const added = await traceStep('Configure fastlane', () =>\n fastlane.addSentryToFastlane(\n projectDir,\n project.organization.slug,\n project.slug,\n ),\n );\n if (added) {\n clack.log.step(\n '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.',\n );\n } else {\n clack.log.warn(\n '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',\n );\n }\n }\n }\n\n clack.log.success(\n '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.',\n );\n}\n\n//Prompt for Sentry project and API key\nasync function getSentryProjectAndApiKey(\n options: WizardOptions,\n): Promise<{ project: SentryProjectData; apiKey: { token: string } }> {\n const { selectedProject, authToken } = await getOrAskForProjectData(options);\n return { project: selectedProject, apiKey: { token: authToken } };\n}\n\nfunction searchXcodeProject(at: string): string[] {\n const projs = findFilesWithExtension(at, '.xcodeproj');\n if (projs.length > 0) {\n return projs;\n }\n\n const workspace = findFilesWithExtension(at, '.xcworkspace');\n if (workspace.length == 0) {\n return [];\n }\n\n const xsworkspacedata = path.join(\n at,\n workspace[0],\n 'contents.xcworkspacedata',\n );\n if (!fs.existsSync(xsworkspacedata)) {\n return [];\n }\n const groupRegex = /location *= *\"group:([^\"]+)\"/gim;\n const content = fs.readFileSync(xsworkspacedata, 'utf8');\n let matches = groupRegex.exec(content);\n\n while (matches) {\n const group = matches[1];\n const groupPath = path.join(at, group);\n if (\n !group.endsWith('Pods.xcodeproj') &&\n group.endsWith('.xcodeproj') &&\n fs.existsSync(groupPath)\n ) {\n projs.push(group);\n }\n matches = groupRegex.exec(content);\n }\n return projs;\n}\n\n//find files with the given extension\nfunction findFilesWithExtension(dir: string, extension: string): string[] {\n const files = fs.readdirSync(dir);\n return files.filter((file) => file.endsWith(extension));\n}\n"]}
@@ -98,6 +98,7 @@ function addCocoaPods(projPath) {
98
98
  podContent.slice(insertIndex);
99
99
  fs.writeFileSync(podfile, newFileContent, 'utf8');
100
100
  loginSpinner = clack.spinner();
101
+ clack.log.step('Sentry pod added to the project podFile.');
101
102
  loginSpinner.start("Running 'pod install'. This may take a few minutes...");
102
103
  _a.label = 1;
103
104
  case 1:
@@ -105,12 +106,12 @@ function addCocoaPods(projPath) {
105
106
  return [4 /*yield*/, bash.execute('pod install --silent')];
106
107
  case 2:
107
108
  _a.sent();
108
- loginSpinner.stop('Sentry pod added to the project.');
109
+ loginSpinner.stop('Running "pod install"');
109
110
  return [3 /*break*/, 4];
110
111
  case 3:
111
112
  e_1 = _a.sent();
112
- clack.log.error("'pod install' failed. You will need to run it manually.");
113
- loginSpinner.stop();
113
+ loginSpinner.stop('Running "pod install"');
114
+ clack.log.error('Failed to run "pod install". You can run it manually for more details.');
114
115
  Sentry.captureException('Sentry pod install failed.');
115
116
  return [3 /*break*/, 4];
116
117
  case 4: return [2 /*return*/, true];
@@ -1 +1 @@
1
- {"version":3,"file":"cocoapod.js","sourceRoot":"","sources":["../../../src/apple/cocoapod.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AACzB,yCAA6B;AAC7B,kDAAsC;AACtC,mDAAuC;AACvC,yEAAyE;AACzE,oDAAwC;AAExC,SAAgB,YAAY,CAAC,QAAgB;IAC3C,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AACvD,CAAC;AAFD,oCAEC;AAED,SAAsB,YAAY,CAAC,QAAgB;;;;;;oBAC3C,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;oBAEzC,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBAEpD,IACE,wDAAwD,CAAC,IAAI,CAAC,UAAU,CAAC,EACzE;wBACA,0BAA0B;wBAC1B,sBAAO,IAAI,EAAC;qBACb;oBAEG,QAAQ,GAAG,+BAA+B,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBAChE,IAAI,CAAC,QAAQ,EAAE;wBAEP,cAAc,GAAG,iCAAiC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;wBAC1E,IAAI,CAAC,cAAc,EAAE;4BACnB,sBAAO,KAAK,EAAC;yBACd;wBACD,QAAQ,GAAG,cAAc,CAAC;qBAC3B;oBAEK,WAAW,GAAG,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;oBAClD,cAAc,GAClB,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;wBAChC,IAAI;wBACJ,QAAQ,CAAC,CAAC,CAAC;wBACX,gBAAgB;wBAChB,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;oBAChC,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;oBAE5C,YAAY,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;oBAErC,YAAY,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;;;;oBAG1E,qBAAM,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAA;;oBAA1C,SAA0C,CAAC;oBAC3C,YAAY,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;;;;oBAEtD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;oBAC3E,YAAY,CAAC,IAAI,EAAE,CAAC;oBACpB,MAAM,CAAC,gBAAgB,CAAC,4BAA4B,CAAC,CAAC;;wBAGxD,sBAAO,IAAI,EAAC;;;;CACb;AA7CD,oCA6CC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\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';\n\nexport function usesCocoaPod(projPath: string): boolean {\n return fs.existsSync(path.join(projPath, 'Podfile'));\n}\n\nexport async function addCocoaPods(projPath: string): Promise<boolean> {\n const podfile = path.join(projPath, 'Podfile');\n\n const podContent = fs.readFileSync(podfile, 'utf8');\n\n if (\n /^\\s*pod\\s+(['\"]Sentry['\"]|['\"]SentrySwiftUI['\"])\\s*$/im.test(podContent)\n ) {\n // Already have Sentry pod\n return true;\n }\n\n let podMatch = /^( *)pod\\s+['\"](\\w+)['\"] *$/im.exec(podContent);\n if (!podMatch) {\n // No Podfile is empty, will try to add Sentry pod after \"use_frameworks!\"\n const frameworkMatch = /^( *)use_frameworks![^\\n]* *$/im.exec(podContent);\n if (!frameworkMatch) {\n return false;\n }\n podMatch = frameworkMatch;\n }\n\n const insertIndex = podMatch.index + podMatch[0].length;\n const newFileContent =\n podContent.slice(0, insertIndex) +\n '\\n' +\n podMatch[1] +\n \"pod 'Sentry'\\n\" +\n podContent.slice(insertIndex);\n fs.writeFileSync(podfile, newFileContent, 'utf8');\n\n const loginSpinner = clack.spinner();\n\n loginSpinner.start(\"Running 'pod install'. This may take a few minutes...\");\n\n try {\n await bash.execute('pod install --silent');\n loginSpinner.stop('Sentry pod added to the project.');\n } catch (e) {\n clack.log.error(\"'pod install' failed. You will need to run it manually.\");\n loginSpinner.stop();\n Sentry.captureException('Sentry pod install failed.');\n }\n\n return true;\n}\n"]}
1
+ {"version":3,"file":"cocoapod.js","sourceRoot":"","sources":["../../../src/apple/cocoapod.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AACzB,yCAA6B;AAC7B,kDAAsC;AACtC,mDAAuC;AACvC,yEAAyE;AACzE,oDAAwC;AAExC,SAAgB,YAAY,CAAC,QAAgB;IAC3C,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AACvD,CAAC;AAFD,oCAEC;AAED,SAAsB,YAAY,CAAC,QAAgB;;;;;;oBAC3C,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;oBAEzC,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBAEpD,IACE,wDAAwD,CAAC,IAAI,CAAC,UAAU,CAAC,EACzE;wBACA,0BAA0B;wBAC1B,sBAAO,IAAI,EAAC;qBACb;oBAEG,QAAQ,GAAG,+BAA+B,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBAChE,IAAI,CAAC,QAAQ,EAAE;wBAEP,cAAc,GAAG,iCAAiC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;wBAC1E,IAAI,CAAC,cAAc,EAAE;4BACnB,sBAAO,KAAK,EAAC;yBACd;wBACD,QAAQ,GAAG,cAAc,CAAC;qBAC3B;oBAEK,WAAW,GAAG,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;oBAClD,cAAc,GAClB,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;wBAChC,IAAI;wBACJ,QAAQ,CAAC,CAAC,CAAC;wBACX,gBAAgB;wBAChB,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;oBAChC,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;oBAE5C,YAAY,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;oBAErC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;oBAC3D,YAAY,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;;;;oBAG1E,qBAAM,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAA;;oBAA1C,SAA0C,CAAC;oBAC3C,YAAY,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;;;;oBAE3C,YAAY,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;oBAC3C,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,wEAAwE,CACzE,CAAC;oBACF,MAAM,CAAC,gBAAgB,CAAC,4BAA4B,CAAC,CAAC;;wBAGxD,sBAAO,IAAI,EAAC;;;;CACb;AAhDD,oCAgDC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\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';\n\nexport function usesCocoaPod(projPath: string): boolean {\n return fs.existsSync(path.join(projPath, 'Podfile'));\n}\n\nexport async function addCocoaPods(projPath: string): Promise<boolean> {\n const podfile = path.join(projPath, 'Podfile');\n\n const podContent = fs.readFileSync(podfile, 'utf8');\n\n if (\n /^\\s*pod\\s+(['\"]Sentry['\"]|['\"]SentrySwiftUI['\"])\\s*$/im.test(podContent)\n ) {\n // Already have Sentry pod\n return true;\n }\n\n let podMatch = /^( *)pod\\s+['\"](\\w+)['\"] *$/im.exec(podContent);\n if (!podMatch) {\n // No Podfile is empty, will try to add Sentry pod after \"use_frameworks!\"\n const frameworkMatch = /^( *)use_frameworks![^\\n]* *$/im.exec(podContent);\n if (!frameworkMatch) {\n return false;\n }\n podMatch = frameworkMatch;\n }\n\n const insertIndex = podMatch.index + podMatch[0].length;\n const newFileContent =\n podContent.slice(0, insertIndex) +\n '\\n' +\n podMatch[1] +\n \"pod 'Sentry'\\n\" +\n podContent.slice(insertIndex);\n fs.writeFileSync(podfile, newFileContent, 'utf8');\n\n const loginSpinner = clack.spinner();\n\n clack.log.step('Sentry pod added to the project podFile.');\n loginSpinner.start(\"Running 'pod install'. This may take a few minutes...\");\n\n try {\n await bash.execute('pod install --silent');\n loginSpinner.stop('Running \"pod install\"');\n } catch (e) {\n loginSpinner.stop('Running \"pod install\"');\n clack.log.error(\n 'Failed to run \"pod install\". You can run it manually for more details.',\n );\n Sentry.captureException('Sentry pod install failed.');\n }\n\n return true;\n}\n"]}
@@ -1 +1 @@
1
- export declare function addCodeSnippetToProject(projPath: string, dsn: string): boolean;
1
+ export declare function addCodeSnippetToProject(projPath: string, files: string[], dsn: string): boolean;
@@ -22,15 +22,20 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
29
  exports.addCodeSnippetToProject = void 0;
27
30
  var fs = __importStar(require("fs"));
28
31
  var path = __importStar(require("path"));
29
32
  var templates = __importStar(require("./templates"));
30
33
  var Sentry = __importStar(require("@sentry/node"));
31
- var swiftAppLaunchRegex = /(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|(init\s*\([^)]*\)\s*{)/im;
34
+ // @ts-ignore - clack is ESM and TS complains about that. It works though
35
+ var prompts_1 = __importDefault(require("@clack/prompts"));
36
+ var swiftAppLaunchRegex = /(func\s+application\s*\(_\sapplication:[^,]+,\s*didFinishLaunchingWithOptions[^,]+:[^)]+\)\s+->\s+Bool\s+{)|func\s+applicationDidFinishLaunching\(_\s+aNotification:\s+Notification\)\s+{/im;
32
37
  var objcAppLaunchRegex = /-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(NSDictionary\s*\*\)\s*launchOptions\s*{/im;
33
- var swiftUIRegex = /struct[^:]+:\s*App\s*{/im;
38
+ var swiftUIRegex = /@main\s+struct[^:]+:\s*App\s*{/im;
34
39
  function isAppDelegateFile(filePath) {
35
40
  var appLaunchRegex = filePath.toLowerCase().endsWith('.swift')
36
41
  ? swiftAppLaunchRegex
@@ -38,38 +43,42 @@ function isAppDelegateFile(filePath) {
38
43
  var fileContent = fs.readFileSync(filePath, 'utf8');
39
44
  return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
40
45
  }
41
- function findAppDidFinishLaunchingWithOptions(dir) {
42
- var files = fs.readdirSync(dir);
46
+ function findAppDidFinishLaunchingWithOptions(dir, files) {
47
+ if (files === void 0) { files = undefined; }
48
+ if (!files) {
49
+ files = fs.readdirSync(dir);
50
+ files = files.map(function (f) { return path.join(dir, f); });
51
+ }
43
52
  //iterate over subdirectories later,
44
53
  //the appdelegate usually is in the top level
45
54
  var dirs = [];
46
55
  for (var _i = 0, files_1 = files; _i < files_1.length; _i++) {
47
- var file = files_1[_i];
48
- var filePath = path.join(dir, file);
49
- if (file.endsWith('.swift') ||
50
- file.endsWith('.m') ||
51
- file.endsWith('.mm')) {
52
- if (isAppDelegateFile(filePath)) {
56
+ var filePath = files_1[_i];
57
+ if (filePath.endsWith('.swift') ||
58
+ filePath.endsWith('.m') ||
59
+ filePath.endsWith('.mm')) {
60
+ if (fs.existsSync(filePath) && isAppDelegateFile(filePath)) {
53
61
  return filePath;
54
62
  }
55
63
  }
56
- else if (!file.startsWith('.') &&
57
- !file.endsWith('.xcodeproj') &&
58
- !file.endsWith('.xcassets') &&
64
+ else if (!filePath.startsWith('.') &&
65
+ !filePath.endsWith('.xcodeproj') &&
66
+ !filePath.endsWith('.xcassets') &&
67
+ fs.existsSync(filePath) &&
59
68
  fs.lstatSync(filePath).isDirectory()) {
60
- dirs.push(file);
69
+ dirs.push(filePath);
61
70
  }
62
71
  }
63
72
  for (var _a = 0, dirs_1 = dirs; _a < dirs_1.length; _a++) {
64
73
  var dr = dirs_1[_a];
65
- var result = findAppDidFinishLaunchingWithOptions(path.join(dir, dr));
74
+ var result = findAppDidFinishLaunchingWithOptions(dr);
66
75
  if (result)
67
76
  return result;
68
77
  }
69
78
  return null;
70
79
  }
71
- function addCodeSnippetToProject(projPath, dsn) {
72
- var appDelegate = findAppDidFinishLaunchingWithOptions(projPath);
80
+ function addCodeSnippetToProject(projPath, files, dsn) {
81
+ var appDelegate = findAppDidFinishLaunchingWithOptions(projPath, files);
73
82
  if (!appDelegate) {
74
83
  return false;
75
84
  }
@@ -85,6 +94,7 @@ function addCodeSnippetToProject(projPath, dsn) {
85
94
  Sentry.setTag('ui-engine', swiftUIRegex.test(fileContent) ? 'swiftui' : 'uikit');
86
95
  if (fileContent.includes(checkForSentryInit)) {
87
96
  //already initialized
97
+ prompts_1.default.log.info('Sentry is already initialized in your AppDelegate. Skipping adding the code snippet.');
88
98
  return true;
89
99
  }
90
100
  var match = appLaunchRegex.exec(fileContent);
@@ -98,12 +108,26 @@ function addCodeSnippetToProject(projPath, dsn) {
98
108
  codeSnippet = " init() {\n".concat(codeSnippet, " }");
99
109
  }
100
110
  var insertIndex = match.index + match[0].length;
101
- var newFileContent = (fileContent.indexOf(importStatement) >= 0 ? '' : importStatement) +
102
- fileContent.slice(0, insertIndex) +
111
+ var newFileContent = fileContent.slice(0, insertIndex) +
103
112
  '\n' +
104
113
  codeSnippet +
105
114
  fileContent.slice(insertIndex);
115
+ if (newFileContent.indexOf(importStatement) < 0) {
116
+ var firstImport = /^[ \t]*import +\w+.*$/m.exec(newFileContent);
117
+ if (firstImport) {
118
+ var importIndex = firstImport.index + firstImport[0].length;
119
+ newFileContent =
120
+ newFileContent.slice(0, importIndex) +
121
+ '\n' +
122
+ importStatement +
123
+ newFileContent.slice(importIndex);
124
+ }
125
+ else {
126
+ newFileContent = importStatement + newFileContent;
127
+ }
128
+ }
106
129
  fs.writeFileSync(appDelegate, newFileContent, 'utf8');
130
+ prompts_1.default.log.step('Added Sentry initialization code snippet to ' + appDelegate);
107
131
  return true;
108
132
  }
109
133
  exports.addCodeSnippetToProject = addCodeSnippetToProject;
@@ -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 fs from 'fs';\nimport * as path from 'path';\nimport * as templates from './templates';\nimport * as Sentry from '@sentry/node';\n\nconst swiftAppLaunchRegex =\n /(func\\s+application\\s*\\(_\\sapplication:[^,]+,\\s*didFinishLaunchingWithOptions[^,]+:[^)]+\\)\\s+->\\s+Bool\\s+{)|(init\\s*\\([^)]*\\)\\s*{)/im;\nconst objcAppLaunchRegex =\n /-\\s*\\(BOOL\\)\\s*application:\\s*\\(UIApplication\\s*\\*\\)\\s*application\\s+didFinishLaunchingWithOptions:\\s*\\(NSDictionary\\s*\\*\\)\\s*launchOptions\\s*{/im;\nconst swiftUIRegex = /struct[^:]+:\\s*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(dir: string): string | null {\n const files = fs.readdirSync(dir);\n //iterate over subdirectories later,\n //the appdelegate usually is in the top level\n const dirs: string[] = [];\n\n for (const file of files) {\n const filePath = path.join(dir, file);\n if (\n file.endsWith('.swift') ||\n file.endsWith('.m') ||\n file.endsWith('.mm')\n ) {\n if (isAppDelegateFile(filePath)) {\n return filePath;\n }\n } else if (\n !file.startsWith('.') &&\n !file.endsWith('.xcodeproj') &&\n !file.endsWith('.xcassets') &&\n fs.lstatSync(filePath).isDirectory()\n ) {\n dirs.push(file);\n }\n }\n\n for (const dr of dirs) {\n const result = findAppDidFinishLaunchingWithOptions(path.join(dir, dr));\n if (result) return result;\n }\n return null;\n}\n\nexport function addCodeSnippetToProject(\n projPath: string,\n dsn: string,\n): boolean {\n const appDelegate = findAppDidFinishLaunchingWithOptions(projPath);\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 return true;\n }\n\n let match = appLaunchRegex.exec(fileContent);\n if (!match) {\n const swiftUIMatch = swiftUIRegex.exec(fileContent);\n if (!swiftUIMatch) {\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 const newFileContent =\n (fileContent.indexOf(importStatement) >= 0 ? '' : importStatement) +\n fileContent.slice(0, insertIndex) +\n '\\n' +\n codeSnippet +\n fileContent.slice(insertIndex);\n fs.writeFileSync(appDelegate, newFileContent, 'utf8');\n\n return true;\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 fs from 'fs';\nimport * as path from 'path';\nimport * as templates from './templates';\nimport * as Sentry from '@sentry/node';\n// @ts-ignore - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\n\nconst swiftAppLaunchRegex =\n /(func\\s+application\\s*\\(_\\sapplication:[^,]+,\\s*didFinishLaunchingWithOptions[^,]+:[^)]+\\)\\s+->\\s+Bool\\s+{)|func\\s+applicationDidFinishLaunching\\(_\\s+aNotification:\\s+Notification\\)\\s+{/im;\nconst objcAppLaunchRegex =\n /-\\s*\\(BOOL\\)\\s*application:\\s*\\(UIApplication\\s*\\*\\)\\s*application\\s+didFinishLaunchingWithOptions:\\s*\\(NSDictionary\\s*\\*\\)\\s*launchOptions\\s*{/im;\nconst swiftUIRegex = /@main\\s+struct[^:]+:\\s*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 !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 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"]}
@@ -1,2 +1,2 @@
1
1
  export declare function fastFile(projectPath: string): string | null;
2
- export declare function addSentryToFastlane(projectPath: string, org: string, project: string, token: string): Promise<boolean>;
2
+ export declare function addSentryToFastlane(projectPath: string, org: string, project: string): Promise<boolean>;