@sentry/wizard 3.7.1 → 3.8.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 (83) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
  3. package/dist/lib/Steps/ChooseIntegration.js +12 -26
  4. package/dist/lib/Steps/ChooseIntegration.js.map +1 -1
  5. package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
  6. package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
  7. package/dist/lib/Steps/Integrations/MobileProject.js.map +1 -1
  8. package/dist/lib/Steps/Integrations/ReactNative.js +2 -2
  9. package/dist/lib/Steps/Integrations/ReactNative.js.map +1 -1
  10. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js +5 -6
  11. package/dist/lib/Steps/Integrations/__tests__/ReactNative.js.map +1 -1
  12. package/dist/package.json +3 -3
  13. package/dist/src/apple/apple-wizard.js +31 -2
  14. package/dist/src/apple/apple-wizard.js.map +1 -1
  15. package/dist/src/apple/cocoapod.d.ts +2 -0
  16. package/dist/src/apple/cocoapod.js +122 -0
  17. package/dist/src/apple/cocoapod.js.map +1 -0
  18. package/dist/src/apple/code-tools.js +22 -12
  19. package/dist/src/apple/code-tools.js.map +1 -1
  20. package/dist/src/apple/fastlane.d.ts +2 -0
  21. package/dist/src/apple/fastlane.js +179 -0
  22. package/dist/src/apple/fastlane.js.map +1 -0
  23. package/dist/src/apple/templates.d.ts +1 -0
  24. package/dist/src/apple/templates.js +7 -3
  25. package/dist/src/apple/templates.js.map +1 -1
  26. package/dist/src/apple/xcode-manager.d.ts +1 -1
  27. package/dist/src/apple/xcode-manager.js +35 -28
  28. package/dist/src/apple/xcode-manager.js.map +1 -1
  29. package/dist/src/nextjs/nextjs-wizard.js +71 -81
  30. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  31. package/dist/src/sourcemaps/sourcemaps-wizard.js +61 -46
  32. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  33. package/dist/src/sourcemaps/tools/nextjs.d.ts +3 -0
  34. package/dist/src/sourcemaps/tools/nextjs.js +135 -0
  35. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -0
  36. package/dist/src/sourcemaps/tools/sentry-cli.js +120 -16
  37. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  38. package/dist/src/sourcemaps/utils/detect-tool.d.ts +1 -1
  39. package/dist/src/sourcemaps/utils/detect-tool.js +1 -0
  40. package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
  41. package/dist/src/sourcemaps/utils/other-wizards.js +35 -12
  42. package/dist/src/sourcemaps/utils/other-wizards.js.map +1 -1
  43. package/dist/src/sveltekit/sentry-cli-setup.d.ts +1 -1
  44. package/dist/src/sveltekit/sentry-cli-setup.js.map +1 -1
  45. package/dist/src/sveltekit/sveltekit-wizard.js +14 -8
  46. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  47. package/dist/src/utils/bash.d.ts +2 -1
  48. package/dist/src/utils/bash.js +14 -2
  49. package/dist/src/utils/bash.js.map +1 -1
  50. package/dist/src/utils/clack-utils.d.ts +7 -14
  51. package/dist/src/utils/clack-utils.js +46 -2
  52. package/dist/src/utils/clack-utils.js.map +1 -1
  53. package/dist/src/utils/package-json.d.ts +1 -1
  54. package/dist/src/utils/package-json.js.map +1 -1
  55. package/dist/src/utils/types.d.ts +24 -0
  56. package/dist/src/utils/types.js.map +1 -1
  57. package/lib/Helper/__tests__/MergeConfig.ts +9 -4
  58. package/lib/Steps/ChooseIntegration.ts +13 -3
  59. package/lib/Steps/Integrations/Cordova.ts +3 -3
  60. package/lib/Steps/Integrations/Electron.ts +1 -2
  61. package/lib/Steps/Integrations/MobileProject.ts +1 -1
  62. package/lib/Steps/Integrations/ReactNative.ts +16 -14
  63. package/lib/Steps/Integrations/__tests__/ReactNative.ts +24 -15
  64. package/package-lock.json +2 -2
  65. package/package.json +3 -3
  66. package/src/apple/apple-wizard.ts +35 -3
  67. package/src/apple/cocoapod.ts +57 -0
  68. package/src/apple/code-tools.ts +80 -57
  69. package/src/apple/fastlane.ts +160 -0
  70. package/src/apple/templates.ts +26 -10
  71. package/src/apple/xcode-manager.ts +137 -120
  72. package/src/nextjs/nextjs-wizard.ts +4 -13
  73. package/src/sourcemaps/sourcemaps-wizard.ts +40 -28
  74. package/src/sourcemaps/tools/nextjs.ts +114 -0
  75. package/src/sourcemaps/tools/sentry-cli.ts +134 -8
  76. package/src/sourcemaps/utils/detect-tool.ts +3 -1
  77. package/src/sourcemaps/utils/other-wizards.ts +32 -13
  78. package/src/sveltekit/sentry-cli-setup.ts +1 -1
  79. package/src/sveltekit/sveltekit-wizard.ts +3 -0
  80. package/src/utils/bash.ts +43 -30
  81. package/src/utils/clack-utils.ts +42 -14
  82. package/src/utils/package-json.ts +1 -1
  83. package/src/utils/types.ts +22 -0
@@ -77,6 +77,8 @@ var codeTools = __importStar(require("./code-tools"));
77
77
  var bash = __importStar(require("../utils/bash"));
78
78
  var Sentry = __importStar(require("@sentry/node"));
79
79
  var telemetry_1 = require("../telemetry");
80
+ var cocoapod = __importStar(require("./cocoapod"));
81
+ var fastlane = __importStar(require("./fastlane"));
80
82
  var xcode = require('xcode');
81
83
  /* eslint-enable @typescript-eslint/no-unused-vars */
82
84
  var clack_utils_1 = require("../utils/clack-utils");
@@ -93,7 +95,7 @@ function runAppleWizard(options) {
93
95
  exports.runAppleWizard = runAppleWizard;
94
96
  function runAppleWizardWithTelementry(options) {
95
97
  return __awaiter(this, void 0, void 0, function () {
96
- var hasCli, projectDir, xcodeProjFiles, xcodeProjFile, pbxproj, _a, project, apiKey, projSource, codeAdded;
98
+ var hasCli, projectDir, xcodeProjFiles, xcodeProjFile, pbxproj, _a, project, apiKey, hasCocoa, podAdded, projSource, codeAdded, addLane;
97
99
  return __generator(this, function (_b) {
98
100
  switch (_b.label) {
99
101
  case 0:
@@ -148,9 +150,22 @@ function runAppleWizardWithTelementry(options) {
148
150
  case 11: return [4 /*yield*/, getSentryProjectAndApiKey(options.promoCode, options.url)];
149
151
  case 12:
150
152
  _a = _b.sent(), project = _a.project, apiKey = _a.apiKey;
153
+ hasCocoa = cocoapod.usesCocoaPod(projectDir);
154
+ if (!hasCocoa) return [3 /*break*/, 14];
155
+ return [4 /*yield*/, (0, telemetry_1.traceStep)('Add CocoaPods reference', function () {
156
+ return cocoapod.addCocoaPods(projectDir);
157
+ })];
158
+ case 13:
159
+ podAdded = _b.sent();
160
+ if (!podAdded) {
161
+ 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
+ }
163
+ _b.label = 14;
164
+ case 14:
151
165
  (0, telemetry_1.traceStep)('Update Xcode project', function () {
152
- xcManager.updateXcodeProject(pbxproj, project, apiKey, true, true);
166
+ xcManager.updateXcodeProject(pbxproj, project, apiKey, !hasCocoa, true);
153
167
  });
168
+ Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');
154
169
  projSource = path.join(projectDir, xcodeProjFile.replace('.xcodeproj', ''));
155
170
  codeAdded = (0, telemetry_1.traceStep)('Add code snippet', function () {
156
171
  return codeTools.addCodeSnippetToProject(projSource, project.keys[0].dsn.public);
@@ -159,6 +174,20 @@ function runAppleWizardWithTelementry(options) {
159
174
  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');
160
175
  return [2 /*return*/];
161
176
  }
177
+ if (!fastlane.fastFile(projectDir)) return [3 /*break*/, 17];
178
+ return [4 /*yield*/, prompts_1.default.confirm({
179
+ message: 'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',
180
+ })];
181
+ case 15:
182
+ addLane = _b.sent();
183
+ if (!addLane) return [3 /*break*/, 17];
184
+ return [4 /*yield*/, (0, telemetry_1.traceStep)('Configure fastlane', function () {
185
+ return fastlane.addSentryToFastlane(projectDir, project.organization.slug, project.slug, apiKey.token);
186
+ })];
187
+ case 16:
188
+ _b.sent();
189
+ _b.label = 17;
190
+ case 17:
162
191
  prompts_1.default.log.success('Sentry was successfully added to your project!');
163
192
  return [2 /*return*/];
164
193
  }
@@ -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 { WizardOptions } from '../utils/types';\nimport * as Sentry from '@sentry/node';\nimport { traceStep, withTelemetry } from '../telemetry';\n\nconst xcode = require('xcode');\n/* eslint-enable @typescript-eslint/no-unused-vars */\n\nimport {\n askForProjectSelection,\n askForSelfHosted,\n askForWizardLogin,\n askToInstallSentryCLI,\n SentryProjectData,\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 traceStep('Update Xcode project', () => {\n xcManager.updateXcodeProject(pbxproj, project, apiKey, true, true);\n });\n\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 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 * 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"]}
@@ -0,0 +1,2 @@
1
+ export declare function usesCocoaPod(projPath: string): boolean;
2
+ export declare function addCocoaPods(projPath: string): Promise<boolean>;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __generator = (this && this.__generator) || function (thisArg, body) {
35
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
36
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
37
+ function verb(n) { return function (v) { return step([n, v]); }; }
38
+ function step(op) {
39
+ if (f) throw new TypeError("Generator is already executing.");
40
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
41
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
42
+ if (y = 0, t) op = [op[0] & 2, t.value];
43
+ switch (op[0]) {
44
+ case 0: case 1: t = op; break;
45
+ case 4: _.label++; return { value: op[1], done: false };
46
+ case 5: _.label++; y = op[1]; op = [0]; continue;
47
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
48
+ default:
49
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
50
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
51
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
52
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
53
+ if (t[2]) _.ops.pop();
54
+ _.trys.pop(); continue;
55
+ }
56
+ op = body.call(thisArg, _);
57
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
58
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
+ }
60
+ };
61
+ Object.defineProperty(exports, "__esModule", { value: true });
62
+ exports.addCocoaPods = exports.usesCocoaPod = void 0;
63
+ var fs = __importStar(require("fs"));
64
+ var path = __importStar(require("path"));
65
+ var bash = __importStar(require("../utils/bash"));
66
+ var Sentry = __importStar(require("@sentry/node"));
67
+ // @ts-ignore - clack is ESM and TS complains about that. It works though
68
+ var clack = __importStar(require("@clack/prompts"));
69
+ function usesCocoaPod(projPath) {
70
+ return fs.existsSync(path.join(projPath, 'Podfile'));
71
+ }
72
+ exports.usesCocoaPod = usesCocoaPod;
73
+ function addCocoaPods(projPath) {
74
+ return __awaiter(this, void 0, void 0, function () {
75
+ var podfile, podContent, podMatch, frameworkMatch, insertIndex, newFileContent, loginSpinner, e_1;
76
+ return __generator(this, function (_a) {
77
+ switch (_a.label) {
78
+ case 0:
79
+ podfile = path.join(projPath, 'Podfile');
80
+ podContent = fs.readFileSync(podfile, 'utf8');
81
+ if (/^\s*pod\s+(['"]Sentry['"]|['"]SentrySwiftUI['"])\s*$/im.test(podContent)) {
82
+ // Already have Sentry pod
83
+ return [2 /*return*/, true];
84
+ }
85
+ podMatch = /^( *)pod\s+['"](\w+)['"] *$/im.exec(podContent);
86
+ if (!podMatch) {
87
+ frameworkMatch = /^( *)use_frameworks![^\n]* *$/im.exec(podContent);
88
+ if (!frameworkMatch) {
89
+ return [2 /*return*/, false];
90
+ }
91
+ podMatch = frameworkMatch;
92
+ }
93
+ insertIndex = podMatch.index + podMatch[0].length;
94
+ newFileContent = podContent.slice(0, insertIndex) +
95
+ '\n' +
96
+ podMatch[1] +
97
+ "pod 'Sentry'\n" +
98
+ podContent.slice(insertIndex);
99
+ fs.writeFileSync(podfile, newFileContent, 'utf8');
100
+ loginSpinner = clack.spinner();
101
+ loginSpinner.start("Running 'pod install'. This may take a few minutes...");
102
+ _a.label = 1;
103
+ case 1:
104
+ _a.trys.push([1, 3, , 4]);
105
+ return [4 /*yield*/, bash.execute('pod install --silent')];
106
+ case 2:
107
+ _a.sent();
108
+ loginSpinner.stop('Sentry pod added to the project.');
109
+ return [3 /*break*/, 4];
110
+ case 3:
111
+ e_1 = _a.sent();
112
+ clack.log.error("'pod install' failed. You will need to run it manually.");
113
+ loginSpinner.stop();
114
+ Sentry.captureException('Sentry pod install failed.');
115
+ return [3 /*break*/, 4];
116
+ case 4: return [2 /*return*/, true];
117
+ }
118
+ });
119
+ });
120
+ }
121
+ exports.addCocoaPods = addCocoaPods;
122
+ //# sourceMappingURL=cocoapod.js.map
@@ -0,0 +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"]}
@@ -32,24 +32,31 @@ var swiftAppLaunchRegex = /(func\s+application\s*\(_\sapplication:[^,]+,\s*didFi
32
32
  var objcAppLaunchRegex = /-\s*\(BOOL\)\s*application:\s*\(UIApplication\s*\*\)\s*application\s+didFinishLaunchingWithOptions:\s*\(NSDictionary\s*\*\)\s*launchOptions\s*{/im;
33
33
  var swiftUIRegex = /struct[^:]+:\s*App\s*{/im;
34
34
  function isAppDelegateFile(filePath) {
35
- var appLaunchRegex = filePath.toLowerCase().endsWith(".swift") ? swiftAppLaunchRegex : objcAppLaunchRegex;
35
+ var appLaunchRegex = filePath.toLowerCase().endsWith('.swift')
36
+ ? swiftAppLaunchRegex
37
+ : objcAppLaunchRegex;
36
38
  var fileContent = fs.readFileSync(filePath, 'utf8');
37
39
  return appLaunchRegex.test(fileContent) || swiftUIRegex.test(fileContent);
38
40
  }
39
41
  function findAppDidFinishLaunchingWithOptions(dir) {
40
42
  var files = fs.readdirSync(dir);
41
- //iterate over subdirectories later,
43
+ //iterate over subdirectories later,
42
44
  //the appdelegate usually is in the top level
43
45
  var dirs = [];
44
46
  for (var _i = 0, files_1 = files; _i < files_1.length; _i++) {
45
47
  var file = files_1[_i];
46
48
  var filePath = path.join(dir, file);
47
- if (file.endsWith(".swift") || file.endsWith(".m") || file.endsWith(".mm")) {
49
+ if (file.endsWith('.swift') ||
50
+ file.endsWith('.m') ||
51
+ file.endsWith('.mm')) {
48
52
  if (isAppDelegateFile(filePath)) {
49
53
  return filePath;
50
54
  }
51
55
  }
52
- else if (!file.startsWith(".") && !file.endsWith(".xcodeproj") && !file.endsWith(".xcassets") && fs.lstatSync(filePath).isDirectory()) {
56
+ else if (!file.startsWith('.') &&
57
+ !file.endsWith('.xcodeproj') &&
58
+ !file.endsWith('.xcassets') &&
59
+ fs.lstatSync(filePath).isDirectory()) {
53
60
  dirs.push(file);
54
61
  }
55
62
  }
@@ -67,13 +74,15 @@ function addCodeSnippetToProject(projPath, dsn) {
67
74
  return false;
68
75
  }
69
76
  var fileContent = fs.readFileSync(appDelegate, 'utf8');
70
- var isSwift = appDelegate.toLowerCase().endsWith(".swift");
77
+ var isSwift = appDelegate.toLowerCase().endsWith('.swift');
71
78
  var appLaunchRegex = isSwift ? swiftAppLaunchRegex : objcAppLaunchRegex;
72
- var importStatement = isSwift ? "import Sentry\n" : "@import Sentry;\n";
73
- var checkForSentryInit = isSwift ? "SentrySDK.start" : "[SentrySDK start";
74
- var codeSnippet = isSwift ? templates.getSwiftSnippet(dsn) : templates.getObjcSnippet(dsn);
75
- Sentry.setTag("code-language", isSwift ? "swift" : "objc");
76
- Sentry.setTag("ui-engine", swiftUIRegex.test(fileContent) ? "swiftui" : "uikit");
79
+ var importStatement = isSwift ? 'import Sentry\n' : '@import Sentry;\n';
80
+ var checkForSentryInit = isSwift ? 'SentrySDK.start' : '[SentrySDK start';
81
+ var codeSnippet = isSwift
82
+ ? templates.getSwiftSnippet(dsn)
83
+ : templates.getObjcSnippet(dsn);
84
+ Sentry.setTag('code-language', isSwift ? 'swift' : 'objc');
85
+ Sentry.setTag('ui-engine', swiftUIRegex.test(fileContent) ? 'swiftui' : 'uikit');
77
86
  if (fileContent.includes(checkForSentryInit)) {
78
87
  //already initialized
79
88
  return true;
@@ -89,8 +98,9 @@ function addCodeSnippetToProject(projPath, dsn) {
89
98
  codeSnippet = " init() {\n".concat(codeSnippet, " }");
90
99
  }
91
100
  var insertIndex = match.index + match[0].length;
92
- var newFileContent = (fileContent.indexOf(importStatement) >= 0 ? "" : importStatement) +
93
- fileContent.slice(0, insertIndex) + "\n" +
101
+ var newFileContent = (fileContent.indexOf(importStatement) >= 0 ? '' : importStatement) +
102
+ fileContent.slice(0, insertIndex) +
103
+ '\n' +
94
104
  codeSnippet +
95
105
  fileContent.slice(insertIndex);
96
106
  fs.writeFileSync(appDelegate, newFileContent, 'utf8');
@@ -1 +1 @@
1
- {"version":3,"file":"code-tools.js","sourceRoot":"","sources":["../../../src/apple/code-tools.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AACzB,yCAA6B;AAC7B,qDAAyC;AACzC,mDAAuC;AAEvC,IAAM,mBAAmB,GAAG,sIAAsI,CAAC;AACnK,IAAM,kBAAkB,GAAG,mJAAmJ,CAAC;AAC/K,IAAM,YAAY,GAAG,0BAA0B,CAAC;AAEhD,SAAS,iBAAiB,CAAC,QAAgB;IACvC,IAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAE5G,IAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACtD,OAAO,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,oCAAoC,CAAC,GAAW;IACrD,IAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,qCAAqC;IACrC,6CAA6C;IAC7C,IAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,KAAmB,UAAK,EAAL,eAAK,EAAL,mBAAK,EAAL,IAAK,EAAE;QAArB,IAAM,IAAI,cAAA;QACX,IAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YACxE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE;gBAC7B,OAAO,QAAQ,CAAC;aACnB;SACJ;aAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE;YACrI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACnB;KACJ;IAED,KAAiB,UAAI,EAAJ,aAAI,EAAJ,kBAAI,EAAJ,IAAI,EAAE;QAAlB,IAAM,EAAE,aAAA;QACT,IAAM,MAAM,GAAG,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QACxE,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;KAC7B;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAgB,uBAAuB,CAAC,QAAgB,EAAE,GAAW;IACjE,IAAM,WAAW,GAAG,oCAAoC,CAAC,QAAQ,CAAC,CAAC;IACnE,IAAI,CAAC,WAAW,EAAE;QACd,OAAO,KAAK,CAAC;KAChB;IAED,IAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzD,IAAM,OAAO,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC7D,IAAM,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAC1E,IAAM,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAC1E,IAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAC5E,IAAI,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAE3F,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAEjF,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QAC1C,qBAAqB;QACrB,OAAO,IAAI,CAAC;KACf;IAED,IAAI,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE;QACR,IAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACnD,IAAI,CAAC,YAAY,EAAE;YACf,OAAO,KAAK,CAAC;SAChB;QACD,yBAAyB;QACzB,KAAK,GAAG,YAAY,CAAC;QACrB,WAAW,GAAG,wBAAiB,WAAW,UAAO,CAAC;KACrD;IAED,IAAM,WAAW,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAClD,IAAM,cAAc,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;QACrF,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,IAAI;QACxC,WAAW;QACX,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACnC,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAEtD,OAAO,IAAI,CAAC;AAChB,CAAC;AAxCD,0DAwCC","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 = /(func\\s+application\\s*\\(_\\sapplication:[^,]+,\\s*didFinishLaunchingWithOptions[^,]+:[^)]+\\)\\s+->\\s+Bool\\s+{)|(init\\s*\\([^)]*\\)\\s*{)/im;\nconst objcAppLaunchRegex = /-\\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\") ? swiftAppLaunchRegex : 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 (file.endsWith(\".swift\") || file.endsWith(\".m\") || file.endsWith(\".mm\")) {\n if (isAppDelegateFile(filePath)) {\n return filePath;\n }\n } else if (!file.startsWith(\".\") && !file.endsWith(\".xcodeproj\") && !file.endsWith(\".xcassets\") && fs.lstatSync(filePath).isDirectory()) {\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(projPath: string, dsn: string): 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 ? templates.getSwiftSnippet(dsn) : templates.getObjcSnippet(dsn);\n\n Sentry.setTag(\"code-language\", isSwift ? \"swift\" : \"objc\");\n Sentry.setTag(\"ui-engine\", swiftUIRegex.test(fileContent) ? \"swiftui\" : \"uikit\");\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 = (fileContent.indexOf(importStatement) >= 0 ? \"\" : importStatement) +\n fileContent.slice(0, insertIndex) + \"\\n\" +\n codeSnippet +\n fileContent.slice(insertIndex);\n fs.writeFileSync(appDelegate, newFileContent, 'utf8');\n\n return true;\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\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"]}
@@ -0,0 +1,2 @@
1
+ export declare function fastFile(projectPath: string): string | null;
2
+ export declare function addSentryToFastlane(projectPath: string, org: string, project: string, token: string): Promise<boolean>;
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __generator = (this && this.__generator) || function (thisArg, body) {
35
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
36
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
37
+ function verb(n) { return function (v) { return step([n, v]); }; }
38
+ function step(op) {
39
+ if (f) throw new TypeError("Generator is already executing.");
40
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
41
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
42
+ if (y = 0, t) op = [op[0] & 2, t.value];
43
+ switch (op[0]) {
44
+ case 0: case 1: t = op; break;
45
+ case 4: _.label++; return { value: op[1], done: false };
46
+ case 5: _.label++; y = op[1]; op = [0]; continue;
47
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
48
+ default:
49
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
50
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
51
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
52
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
53
+ if (t[2]) _.ops.pop();
54
+ _.trys.pop(); continue;
55
+ }
56
+ op = body.call(thisArg, _);
57
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
58
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
+ }
60
+ };
61
+ Object.defineProperty(exports, "__esModule", { value: true });
62
+ exports.addSentryToFastlane = exports.fastFile = void 0;
63
+ var fs = __importStar(require("fs"));
64
+ var path = __importStar(require("path"));
65
+ var templates = __importStar(require("./templates"));
66
+ var clack_utils_1 = require("../utils/clack-utils");
67
+ function fastFile(projectPath) {
68
+ var fastlanePath = path.join(projectPath, 'fastlane', 'Fastfile');
69
+ return fs.existsSync(fastlanePath) ? fastlanePath : null;
70
+ }
71
+ exports.fastFile = fastFile;
72
+ function findIOSPlatform(content) {
73
+ var platformRegex = /^ *platform\s+:([^ ]+)[^\n]*\n/gim;
74
+ var match = platformRegex.exec(content);
75
+ if (!match) {
76
+ // No platform found, treat whole file as one platform.
77
+ return { index: 0, length: content.length };
78
+ }
79
+ var index = -1;
80
+ while (match) {
81
+ if (match[1] === 'ios') {
82
+ index = match.index + match[0].length;
83
+ break;
84
+ }
85
+ match = platformRegex.exec(content);
86
+ }
87
+ if (index === -1) {
88
+ return null;
89
+ }
90
+ //After finding the platform, we need to find the end of the platform block.
91
+ //This solution has the assumption that the file is well formed,
92
+ //which is not a perfect solution, but it's good enough assumption.
93
+ var platformEndRegex = /^end[^\n]*/gim;
94
+ match = platformEndRegex.exec(content.slice(index));
95
+ if (!match) {
96
+ return null;
97
+ }
98
+ return { index: index, length: match.index };
99
+ }
100
+ function findLanes(content) {
101
+ var laneRegex = /^ {2}lane\s+:([^ ]+)[^\n]*\n/gim;
102
+ var match = laneRegex.exec(content);
103
+ if (!match) {
104
+ return null;
105
+ }
106
+ var lanes = [];
107
+ while (match) {
108
+ var laneEnd = /^ {2}end/m.exec(content.slice(match.index + match[0].length));
109
+ if (laneEnd === null) {
110
+ return null;
111
+ }
112
+ lanes.push({
113
+ index: match.index + match[0].length,
114
+ length: laneEnd.index,
115
+ name: match[1],
116
+ });
117
+ match = laneRegex.exec(content);
118
+ }
119
+ return lanes;
120
+ }
121
+ function addSentryToLane(content, lane, org, project, token) {
122
+ var laneContent = content.slice(lane.index, lane.index + lane.length);
123
+ var sentryCLIMatch = /sentry_cli\s*\([^)]+\)/gim.exec(laneContent);
124
+ if (sentryCLIMatch) {
125
+ // Sentry already added to lane. Update it.
126
+ return (content.slice(0, sentryCLIMatch.index + lane.index) +
127
+ templates.getFastlaneSnippet(org, project, token).trim() +
128
+ content.slice(sentryCLIMatch.index + sentryCLIMatch[0].length + lane.index));
129
+ }
130
+ // Sentry not added to lane. Add it.
131
+ return (content.slice(0, lane.index + lane.length) +
132
+ '\n' +
133
+ templates.getFastlaneSnippet(org, project, token) +
134
+ '\n' +
135
+ content.slice(lane.index + lane.length));
136
+ }
137
+ function addSentryToFastlane(projectPath, org, project, token) {
138
+ return __awaiter(this, void 0, void 0, function () {
139
+ var fastFilePath, fileContent, platform, platformContent, lanes, newFileContent, laneNames, selectedLane;
140
+ return __generator(this, function (_a) {
141
+ switch (_a.label) {
142
+ case 0:
143
+ fastFilePath = fastFile(projectPath);
144
+ if (!fastFilePath) {
145
+ return [2 /*return*/, false];
146
+ }
147
+ fileContent = fs.readFileSync(fastFilePath, 'utf8');
148
+ platform = findIOSPlatform(fileContent);
149
+ if (!platform) {
150
+ return [2 /*return*/, false];
151
+ }
152
+ platformContent = fileContent.slice(platform.index, platform.index + platform.length);
153
+ lanes = findLanes(platformContent);
154
+ lanes === null || lanes === void 0 ? void 0 : lanes.forEach(function (l) { return (l.index += platform.index); });
155
+ if (!lanes || lanes.length === 0) {
156
+ return [2 /*return*/, false];
157
+ }
158
+ if (!(lanes.length === 1)) return [3 /*break*/, 1];
159
+ newFileContent = addSentryToLane(fileContent, lanes[0], org, project, token);
160
+ return [3 /*break*/, 3];
161
+ case 1:
162
+ laneNames = lanes.map(function (l) { return l.name; });
163
+ return [4 /*yield*/, (0, clack_utils_1.askForItemSelection)(laneNames, 'Select lane to add Sentry to:')];
164
+ case 2:
165
+ selectedLane = _a.sent();
166
+ if (selectedLane === undefined) {
167
+ return [2 /*return*/, false];
168
+ }
169
+ newFileContent = addSentryToLane(fileContent, lanes[selectedLane.index], org, project, token);
170
+ _a.label = 3;
171
+ case 3:
172
+ fs.writeFileSync(fastFilePath, newFileContent, 'utf8');
173
+ return [2 /*return*/, true];
174
+ }
175
+ });
176
+ });
177
+ }
178
+ exports.addSentryToFastlane = addSentryToFastlane;
179
+ //# sourceMappingURL=fastlane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastlane.js","sourceRoot":"","sources":["../../../src/apple/fastlane.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as templates from './templates';\nimport { askForItemSelection } from '../utils/clack-utils';\n\nexport function fastFile(projectPath: string): string | null {\n const fastlanePath = path.join(projectPath, 'fastlane', 'Fastfile');\n return fs.existsSync(fastlanePath) ? fastlanePath : null;\n}\n\nfunction findIOSPlatform(\n content: string,\n): { index: number; length: number } | null {\n const platformRegex = /^ *platform\\s+:([^ ]+)[^\\n]*\\n/gim;\n let match = platformRegex.exec(content);\n if (!match) {\n // No platform found, treat whole file as one platform.\n return { index: 0, length: content.length };\n }\n\n let index = -1;\n while (match) {\n if (match[1] === 'ios') {\n index = match.index + match[0].length;\n break;\n }\n match = platformRegex.exec(content);\n }\n\n if (index === -1) {\n return null;\n }\n\n //After finding the platform, we need to find the end of the platform block.\n //This solution has the assumption that the file is well formed,\n //which is not a perfect solution, but it's good enough assumption.\n const platformEndRegex = /^end[^\\n]*/gim;\n match = platformEndRegex.exec(content.slice(index));\n if (!match) {\n return null;\n }\n\n return { index, length: match.index };\n}\n\nfunction findLanes(\n content: string,\n): { index: number; length: number; name: string }[] | null {\n const laneRegex = /^ {2}lane\\s+:([^ ]+)[^\\n]*\\n/gim;\n let match = laneRegex.exec(content);\n if (!match) {\n return null;\n }\n\n const lanes: { index: number; length: number; name: string }[] = [];\n while (match) {\n const laneEnd = /^ {2}end/m.exec(\n content.slice(match.index + match[0].length),\n );\n if (laneEnd === null) {\n return null;\n }\n lanes.push({\n index: match.index + match[0].length,\n length: laneEnd.index,\n name: match[1],\n });\n match = laneRegex.exec(content);\n }\n return lanes;\n}\n\nfunction addSentryToLane(\n content: string,\n lane: { index: number; length: number; name: string },\n org: string,\n project: string,\n token: string,\n): string {\n const laneContent = content.slice(lane.index, lane.index + lane.length);\n const sentryCLIMatch = /sentry_cli\\s*\\([^)]+\\)/gim.exec(laneContent);\n if (sentryCLIMatch) {\n // Sentry already added to lane. Update it.\n return (\n content.slice(0, sentryCLIMatch.index + lane.index) +\n templates.getFastlaneSnippet(org, project, token).trim() +\n content.slice(\n sentryCLIMatch.index + sentryCLIMatch[0].length + lane.index,\n )\n );\n }\n\n // Sentry not added to lane. Add it.\n return (\n content.slice(0, lane.index + lane.length) +\n '\\n' +\n templates.getFastlaneSnippet(org, project, token) +\n '\\n' +\n content.slice(lane.index + lane.length)\n );\n}\n\nexport async function addSentryToFastlane(\n projectPath: string,\n org: string,\n project: string,\n token: string,\n): Promise<boolean> {\n const fastFilePath = fastFile(projectPath);\n if (!fastFilePath) {\n return false;\n }\n\n const fileContent = fs.readFileSync(fastFilePath, 'utf8');\n const platform = findIOSPlatform(fileContent);\n if (!platform) {\n return false;\n }\n\n const platformContent = fileContent.slice(\n platform.index,\n platform.index + platform.length,\n );\n const lanes = findLanes(platformContent);\n lanes?.forEach((l) => (l.index += platform.index));\n\n if (!lanes || lanes.length === 0) {\n return false;\n }\n\n let newFileContent: string | undefined;\n if (lanes.length === 1) {\n newFileContent = addSentryToLane(\n fileContent,\n lanes[0],\n org,\n project,\n token,\n );\n } else {\n const laneNames = lanes.map((l) => l.name);\n const selectedLane = await askForItemSelection(\n laneNames,\n 'Select lane to add Sentry to:',\n );\n if (selectedLane === undefined) {\n return false;\n }\n newFileContent = addSentryToLane(\n fileContent,\n lanes[selectedLane.index],\n org,\n project,\n token,\n );\n }\n\n fs.writeFileSync(fastFilePath, newFileContent, 'utf8');\n return true;\n}\n"]}
@@ -2,3 +2,4 @@ export declare function getRunScriptTemplate(orgSlug: string, projectSlug: strin
2
2
  export declare const scriptInputPath = "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"";
3
3
  export declare function getSwiftSnippet(dsn: string): string;
4
4
  export declare function getObjcSnippet(dsn: string): string;
5
+ export declare function getFastlaneSnippet(org: string, project: string, token: string): string;
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getObjcSnippet = exports.getSwiftSnippet = exports.scriptInputPath = exports.getRunScriptTemplate = void 0;
3
+ exports.getFastlaneSnippet = exports.getObjcSnippet = exports.getSwiftSnippet = exports.scriptInputPath = exports.getRunScriptTemplate = void 0;
4
4
  function getRunScriptTemplate(orgSlug, projectSlug, apiKey, uploadSource) {
5
5
  if (uploadSource === void 0) { uploadSource = true; }
6
6
  // eslint-disable-next-line no-useless-escape
7
- return "# This script is responsable to upload debug symbols and source context for Sentry.\\nif which sentry-cli >/dev/null; then\\nexport SENTRY_ORG=".concat(orgSlug, "\\nexport SENTRY_PROJECT=").concat(projectSlug, "\\nexport SENTRY_AUTH_TOKEN=").concat(apiKey, "\\nERROR=$(sentry-cli debug-files upload ").concat(uploadSource ? "--include-sources " : "", "\"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null)\\nif [ ! $? -eq 0 ]; then\\necho \"warning: sentry-cli - $ERROR\"\\nfi\\nelse\\necho \"warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases\"\\nfi\\n");
7
+ return "# This script is responsable to upload debug symbols and source context for Sentry.\\nif which sentry-cli >/dev/null; then\\nexport SENTRY_ORG=".concat(orgSlug, "\\nexport SENTRY_PROJECT=").concat(projectSlug, "\\nexport SENTRY_AUTH_TOKEN=").concat(apiKey, "\\nERROR=$(sentry-cli debug-files upload ").concat(uploadSource ? '--include-sources ' : '', "\"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null)\\nif [ ! $? -eq 0 ]; then\\necho \"warning: sentry-cli - $ERROR\"\\nfi\\nelse\\necho \"warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases\"\\nfi\\n");
8
8
  }
9
9
  exports.getRunScriptTemplate = getRunScriptTemplate;
10
- exports.scriptInputPath = "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"";
10
+ exports.scriptInputPath = '"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}"';
11
11
  function getSwiftSnippet(dsn) {
12
12
  return " SentrySDK.start { options in\n options.dsn = \"".concat(dsn, "\"\n options.debug = true // Enabled debug when first installing is always helpful\n options.enableTracing = true \n\n // Uncomment the following lines to add more data to your events\n // options.attachScreenshot = true // This adds a screenshot to the error events\n // options.attachViewHierarchy = true // This adds the view hierarchy to the error events\n }\n // Remove the next line after confirming that your Sentry integration is working.\n SentrySDK.capture(message: \"This app uses Sentry! :)\")\n");
13
13
  }
@@ -16,4 +16,8 @@ function getObjcSnippet(dsn) {
16
16
  return " [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {\n options.dsn = @\"".concat(dsn, "\";\n options.debug = YES; // Enabled debug when first installing is always helpful\n options.enableTracing = YES;\n\n //Uncomment the following lines to add more data to your events\n //options.attachScreenshot = YES; //This will add a screenshot to the error events\n //options.attachViewHierarchy = YES; //This will add the view hierarchy to the error events\n }];\n //Remove the next line after confirming that your Sentry integration is working.\n [SentrySDK captureMessage:@\"This app uses Sentry!\"];\n");
17
17
  }
18
18
  exports.getObjcSnippet = getObjcSnippet;
19
+ function getFastlaneSnippet(org, project, token) {
20
+ return " sentry_cli(\n auth_token: '".concat(token, "',\n org_slug: '").concat(org, "',\n project_slug: '").concat(project, "',\n include_sources: true\n )");
21
+ }
22
+ exports.getFastlaneSnippet = getFastlaneSnippet;
19
23
  //# sourceMappingURL=templates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/apple/templates.ts"],"names":[],"mappings":";;;AAAA,SAAgB,oBAAoB,CAChC,OAAe,EACf,WAAmB,EACnB,MAAc,EACd,YAAmB;IAAnB,6BAAA,EAAA,mBAAmB;IAEnB,6CAA6C;IAC7C,OAAO,yJAAkJ,OAAO,sCAA4B,WAAW,yCAA+B,MAAM,sDAA4C,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,oPAAiP,CAAC;AACtjB,CAAC;AARD,oDAQC;AAEY,QAAA,eAAe,GAAG,+FAA+F,CAAC;AAE/H,SAAgB,eAAe,CAAC,GAAW;IACvC,OAAO,4EACkB,GAAG,4kBASiC,CAAC;AAClE,CAAC;AAZD,0CAYC;AAED,SAAgB,cAAc,CAAC,GAAW;IACtC,OAAO,0GACe,GAAG,8iBAS8B,CAAC;AAC5D,CAAC;AAZD,wCAYC","sourcesContent":["export function getRunScriptTemplate(\n orgSlug: string,\n projectSlug: string,\n apiKey: string,\n uploadSource = true,\n): string {\n // eslint-disable-next-line no-useless-escape\n return `# This script is responsable to upload debug symbols and source context for Sentry.\\\\nif which sentry-cli >/dev/null; then\\\\nexport SENTRY_ORG=${orgSlug}\\\\nexport SENTRY_PROJECT=${projectSlug}\\\\nexport SENTRY_AUTH_TOKEN=${apiKey}\\\\nERROR=$(sentry-cli debug-files upload ${uploadSource ? \"--include-sources \" : \"\"}\\\"$DWARF_DSYM_FOLDER_PATH\\\" 2>&1 >/dev/null)\\\\nif [ ! $? -eq 0 ]; then\\\\necho \\\"warning: sentry-cli - $ERROR\\\"\\\\nfi\\\\nelse\\\\necho \\\"warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases\\\"\\\\nfi\\\\n`;\n}\n\nexport const scriptInputPath = \"\\\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\\\"\";\n\nexport function getSwiftSnippet(dsn: string): string {\n return ` SentrySDK.start { options in\n options.dsn = \"${dsn}\"\n options.debug = true // Enabled debug when first installing is always helpful\n options.enableTracing = true \n\n // Uncomment the following lines to add more data to your events\n // options.attachScreenshot = true // This adds a screenshot to the error events\n // options.attachViewHierarchy = true // This adds the view hierarchy to the error events\n }\n // Remove the next line after confirming that your Sentry integration is working.\n SentrySDK.capture(message: \"This app uses Sentry! :)\")\\n`;\n}\n\nexport function getObjcSnippet(dsn: string): string {\n return ` [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {\n options.dsn = @\"${dsn}\";\n options.debug = YES; // Enabled debug when first installing is always helpful\n options.enableTracing = YES;\n\n //Uncomment the following lines to add more data to your events\n //options.attachScreenshot = YES; //This will add a screenshot to the error events\n //options.attachViewHierarchy = YES; //This will add the view hierarchy to the error events\n }];\n //Remove the next line after confirming that your Sentry integration is working.\n [SentrySDK captureMessage:@\"This app uses Sentry!\"];\\n`;\n}"]}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/apple/templates.ts"],"names":[],"mappings":";;;AAAA,SAAgB,oBAAoB,CAClC,OAAe,EACf,WAAmB,EACnB,MAAc,EACd,YAAmB;IAAnB,6BAAA,EAAA,mBAAmB;IAEnB,6CAA6C;IAC7C,OAAO,yJAAkJ,OAAO,sCAA4B,WAAW,yCAA+B,MAAM,sDAC1O,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,oPACiM,CAAC;AAC9O,CAAC;AAVD,oDAUC;AAEY,QAAA,eAAe,GAC1B,6FAA6F,CAAC;AAEhG,SAAgB,eAAe,CAAC,GAAW;IACzC,OAAO,4EACoB,GAAG,4kBASiC,CAAC;AAClE,CAAC;AAZD,0CAYC;AAED,SAAgB,cAAc,CAAC,GAAW;IACxC,OAAO,0GACiB,GAAG,8iBAS8B,CAAC;AAC5D,CAAC;AAZD,wCAYC;AAED,SAAgB,kBAAkB,CAChC,GAAW,EACX,OAAe,EACf,KAAa;IAEb,OAAO,8CACY,KAAK,kCACP,GAAG,sCACC,OAAO,2CAExB,CAAC;AACP,CAAC;AAXD,gDAWC","sourcesContent":["export function getRunScriptTemplate(\n orgSlug: string,\n projectSlug: string,\n apiKey: string,\n uploadSource = true,\n): string {\n // eslint-disable-next-line no-useless-escape\n return `# This script is responsable to upload debug symbols and source context for Sentry.\\\\nif which sentry-cli >/dev/null; then\\\\nexport SENTRY_ORG=${orgSlug}\\\\nexport SENTRY_PROJECT=${projectSlug}\\\\nexport SENTRY_AUTH_TOKEN=${apiKey}\\\\nERROR=$(sentry-cli debug-files upload ${\n uploadSource ? '--include-sources ' : ''\n }\"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null)\\\\nif [ ! $? -eq 0 ]; then\\\\necho \"warning: sentry-cli - $ERROR\"\\\\nfi\\\\nelse\\\\necho \"warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases\"\\\\nfi\\\\n`;\n}\n\nexport const scriptInputPath =\n '\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"';\n\nexport function getSwiftSnippet(dsn: string): string {\n return ` SentrySDK.start { options in\n options.dsn = \"${dsn}\"\n options.debug = true // Enabled debug when first installing is always helpful\n options.enableTracing = true \n\n // Uncomment the following lines to add more data to your events\n // options.attachScreenshot = true // This adds a screenshot to the error events\n // options.attachViewHierarchy = true // This adds the view hierarchy to the error events\n }\n // Remove the next line after confirming that your Sentry integration is working.\n SentrySDK.capture(message: \"This app uses Sentry! :)\")\\n`;\n}\n\nexport function getObjcSnippet(dsn: string): string {\n return ` [SentrySDK startWithConfigureOptions:^(SentryOptions * options) {\n options.dsn = @\"${dsn}\";\n options.debug = YES; // Enabled debug when first installing is always helpful\n options.enableTracing = YES;\n\n //Uncomment the following lines to add more data to your events\n //options.attachScreenshot = YES; //This will add a screenshot to the error events\n //options.attachViewHierarchy = YES; //This will add the view hierarchy to the error events\n }];\n //Remove the next line after confirming that your Sentry integration is working.\n [SentrySDK captureMessage:@\"This app uses Sentry!\"];\\n`;\n}\n\nexport function getFastlaneSnippet(\n org: string,\n project: string,\n token: string,\n): string {\n return ` sentry_cli(\n auth_token: '${token}',\n org_slug: '${org}',\n project_slug: '${project}',\n include_sources: true\n )`;\n}\n"]}