@sentry/wizard 6.11.0 → 6.13.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.
- package/CHANGELOG.md +64 -0
- package/dist/bin.js +16 -1
- package/dist/bin.js.map +1 -1
- package/dist/e2e-tests/tests/angular-17.test.js +3 -4
- package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
- package/dist/e2e-tests/tests/angular-19.test.js +3 -4
- package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
- package/dist/e2e-tests/tests/cloudflare-worker.test.js +5 -0
- package/dist/e2e-tests/tests/cloudflare-worker.test.js.map +1 -1
- package/dist/e2e-tests/tests/flutter.test.js +60 -0
- package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
- package/dist/e2e-tests/tests/help-message.test.js +8 -3
- package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
- package/dist/e2e-tests/tests/nuxt-3.test.js +12 -6
- package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
- package/dist/e2e-tests/tests/nuxt-4.test.js +12 -6
- package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
- package/dist/e2e-tests/tests/pnpm-workspace.test.js +8 -4
- package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
- package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js +96 -0
- package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js.map +1 -0
- package/dist/e2e-tests/tests/react-router.test.js +6 -7
- package/dist/e2e-tests/tests/react-router.test.js.map +1 -1
- package/dist/e2e-tests/tests/remix.test.js +2 -4
- package/dist/e2e-tests/tests/remix.test.js.map +1 -1
- package/dist/e2e-tests/tests/sveltekit-hooks.test.js +24 -8
- package/dist/e2e-tests/tests/sveltekit-hooks.test.js.map +1 -1
- package/dist/e2e-tests/tests/sveltekit-tracing.test.js +8 -4
- package/dist/e2e-tests/tests/sveltekit-tracing.test.js.map +1 -1
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/lib/Steps/Integrations/Electron.js +2 -2
- package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
- package/dist/src/android/android-wizard.js +3 -0
- package/dist/src/android/android-wizard.js.map +1 -1
- package/dist/src/angular/codemods/main.d.ts +1 -1
- package/dist/src/angular/codemods/main.js +0 -1
- package/dist/src/angular/codemods/main.js.map +1 -1
- package/dist/src/apple/apple-wizard.js +2 -3
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/check-installed-cli.d.ts +1 -1
- package/dist/src/apple/check-installed-cli.js +13 -7
- package/dist/src/apple/check-installed-cli.js.map +1 -1
- package/dist/src/apple/code-tools.js +17 -3
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/configure-package-manager.js +18 -5
- package/dist/src/apple/configure-package-manager.js.map +1 -1
- package/dist/src/apple/configure-xcode-project.js +8 -1
- package/dist/src/apple/configure-xcode-project.js.map +1 -1
- package/dist/src/apple/lookup-xcode-project.d.ts +8 -5
- package/dist/src/apple/lookup-xcode-project.js +22 -17
- package/dist/src/apple/lookup-xcode-project.js.map +1 -1
- package/dist/src/apple/options.d.ts +5 -0
- package/dist/src/apple/options.js.map +1 -1
- package/dist/src/apple/sentry-swift-package.d.ts +4 -0
- package/dist/src/apple/sentry-swift-package.js +17 -0
- package/dist/src/apple/sentry-swift-package.js.map +1 -0
- package/dist/src/apple/snapshots/apple-snapshots-wizard.d.ts +2 -0
- package/dist/src/apple/snapshots/apple-snapshots-wizard.js +251 -0
- package/dist/src/apple/snapshots/apple-snapshots-wizard.js.map +1 -0
- package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.d.ts +13 -0
- package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.js +48 -0
- package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.js.map +1 -0
- package/dist/src/apple/snapshots/snapshot-test-file.d.ts +18 -0
- package/dist/src/apple/snapshots/snapshot-test-file.js +122 -0
- package/dist/src/apple/snapshots/snapshot-test-file.js.map +1 -0
- package/dist/src/apple/snapshots/snapshot-verification-scheme.d.ts +6 -0
- package/dist/src/apple/snapshots/snapshot-verification-scheme.js +147 -0
- package/dist/src/apple/snapshots/snapshot-verification-scheme.js.map +1 -0
- package/dist/src/apple/snapshots/snapshotpreviews-package.d.ts +4 -0
- package/dist/src/apple/snapshots/snapshotpreviews-package.js +8 -0
- package/dist/src/apple/snapshots/snapshotpreviews-package.js.map +1 -0
- package/dist/src/apple/snapshots/snapshots-cli-preflight.d.ts +23 -0
- package/dist/src/apple/snapshots/snapshots-cli-preflight.js +136 -0
- package/dist/src/apple/snapshots/snapshots-cli-preflight.js.map +1 -0
- package/dist/src/apple/xcode-manager.d.ts +59 -1
- package/dist/src/apple/xcode-manager.js +507 -106
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/cloudflare/cloudflare-wizard.js +5 -0
- package/dist/src/cloudflare/cloudflare-wizard.js.map +1 -1
- package/dist/src/cloudflare/sdk-setup.d.ts +1 -0
- package/dist/src/cloudflare/sdk-setup.js.map +1 -1
- package/dist/src/cloudflare/templates.d.ts +1 -0
- package/dist/src/cloudflare/templates.js +7 -1
- package/dist/src/cloudflare/templates.js.map +1 -1
- package/dist/src/cloudflare/wrap-worker.d.ts +1 -0
- package/dist/src/cloudflare/wrap-worker.js +7 -0
- package/dist/src/cloudflare/wrap-worker.js.map +1 -1
- package/dist/src/flutter/flutter-wizard.js +3 -0
- package/dist/src/flutter/flutter-wizard.js.map +1 -1
- package/dist/src/nextjs/templates.js +12 -6
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/nuxt/templates.js +12 -6
- package/dist/src/nuxt/templates.js.map +1 -1
- package/dist/src/react-native/expo.d.ts +6 -0
- package/dist/src/react-native/expo.js +27 -1
- package/dist/src/react-native/expo.js.map +1 -1
- package/dist/src/react-native/git.d.ts +5 -0
- package/dist/src/react-native/git.js +32 -1
- package/dist/src/react-native/git.js.map +1 -1
- package/dist/src/react-native/javascript.js +3 -1
- package/dist/src/react-native/javascript.js.map +1 -1
- package/dist/src/react-native/react-native-wizard.js +12 -6
- package/dist/src/react-native/react-native-wizard.js.map +1 -1
- package/dist/src/react-router/codemods/client.entry.d.ts +1 -1
- package/dist/src/react-router/codemods/client.entry.js +124 -26
- package/dist/src/react-router/codemods/client.entry.js.map +1 -1
- package/dist/src/react-router/codemods/react-router-config.js +1 -1
- package/dist/src/react-router/codemods/react-router-config.js.map +1 -1
- package/dist/src/react-router/codemods/server-entry.d.ts +1 -1
- package/dist/src/react-router/codemods/server-entry.js +40 -4
- package/dist/src/react-router/codemods/server-entry.js.map +1 -1
- package/dist/src/react-router/codemods/vite.js +46 -1
- package/dist/src/react-router/codemods/vite.js.map +1 -1
- package/dist/src/react-router/react-router-wizard.js +62 -21
- package/dist/src/react-router/react-router-wizard.js.map +1 -1
- package/dist/src/react-router/sdk-setup.d.ts +5 -3
- package/dist/src/react-router/sdk-setup.js +44 -16
- package/dist/src/react-router/sdk-setup.js.map +1 -1
- package/dist/src/react-router/templates.d.ts +2 -4
- package/dist/src/react-router/templates.js +89 -87
- package/dist/src/react-router/templates.js.map +1 -1
- package/dist/src/remix/sdk-setup.js +1 -2
- package/dist/src/remix/sdk-setup.js.map +1 -1
- package/dist/src/run.d.ts +4 -1
- package/dist/src/run.js +13 -0
- package/dist/src/run.js.map +1 -1
- package/dist/src/sourcemaps/tools/remix.js +4 -4
- package/dist/src/sourcemaps/tools/remix.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.js +1 -1
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup/setup.js +17 -4
- package/dist/src/sveltekit/sdk-setup/setup.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup/vite.js +1 -1
- package/dist/src/sveltekit/sdk-setup/vite.js.map +1 -1
- package/dist/src/sveltekit/templates.js +12 -6
- package/dist/src/sveltekit/templates.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +10 -0
- package/dist/src/utils/ast-utils.js +19 -1
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack/index.d.ts +2 -1
- package/dist/src/utils/clack/index.js +17 -6
- package/dist/src/utils/clack/index.js.map +1 -1
- package/dist/src/utils/files.d.ts +2 -0
- package/dist/src/utils/files.js +58 -0
- package/dist/src/utils/files.js.map +1 -0
- package/dist/src/utils/git.d.ts +3 -1
- package/dist/src/utils/git.js +2 -1
- package/dist/src/utils/git.js.map +1 -1
- package/dist/src/utils/line-endings.d.ts +1 -0
- package/dist/src/utils/line-endings.js +76 -0
- package/dist/src/utils/line-endings.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/test/angular/angular-wizard.test.js +0 -5
- package/dist/test/angular/angular-wizard.test.js.map +1 -1
- package/dist/test/apple/code-tools.test.js +78 -0
- package/dist/test/apple/code-tools.test.js.map +1 -1
- package/dist/test/apple/configure-package-manager.test.d.ts +1 -0
- package/dist/test/apple/configure-package-manager.test.js +161 -0
- package/dist/test/apple/configure-package-manager.test.js.map +1 -0
- package/dist/test/apple/lookup-xcode-project.test.d.ts +1 -0
- package/dist/test/apple/lookup-xcode-project.test.js +167 -0
- package/dist/test/apple/lookup-xcode-project.test.js.map +1 -0
- package/dist/test/apple/snapshots/apple-snapshots-wizard.test.d.ts +1 -0
- package/dist/test/apple/snapshots/apple-snapshots-wizard.test.js +487 -0
- package/dist/test/apple/snapshots/apple-snapshots-wizard.test.js.map +1 -0
- package/dist/test/apple/snapshots/hosted-test-target-fixture.d.ts +24 -0
- package/dist/test/apple/snapshots/hosted-test-target-fixture.js +191 -0
- package/dist/test/apple/snapshots/hosted-test-target-fixture.js.map +1 -0
- package/dist/test/apple/snapshots/snapshot-test-file.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshot-test-file.test.js +110 -0
- package/dist/test/apple/snapshots/snapshot-test-file.test.js.map +1 -0
- package/dist/test/apple/snapshots/snapshot-verification-scheme.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshot-verification-scheme.test.js +146 -0
- package/dist/test/apple/snapshots/snapshot-verification-scheme.test.js.map +1 -0
- package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.js +186 -0
- package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.js.map +1 -0
- package/dist/test/apple/snapshots/snapshots-cli-preflight.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshots-cli-preflight.test.js +192 -0
- package/dist/test/apple/snapshots/snapshots-cli-preflight.test.js.map +1 -0
- package/dist/test/apple/snapshots/source-file-insertion.test.d.ts +1 -0
- package/dist/test/apple/snapshots/source-file-insertion.test.js +77 -0
- package/dist/test/apple/snapshots/source-file-insertion.test.js.map +1 -0
- package/dist/test/apple/xcode-manager.test.js +452 -43
- package/dist/test/apple/xcode-manager.test.js.map +1 -1
- package/dist/test/cloudflare/sdk-setup.test.js +20 -2
- package/dist/test/cloudflare/sdk-setup.test.js.map +1 -1
- package/dist/test/cloudflare/templates.test.js +54 -0
- package/dist/test/cloudflare/templates.test.js.map +1 -1
- package/dist/test/cloudflare/wrap-worker.test.js +74 -11
- package/dist/test/cloudflare/wrap-worker.test.js.map +1 -1
- package/dist/test/constants.test.d.ts +1 -0
- package/dist/test/constants.test.js +12 -0
- package/dist/test/constants.test.js.map +1 -0
- package/dist/test/nextjs/templates.test.js +66 -33
- package/dist/test/nextjs/templates.test.js.map +1 -1
- package/dist/test/nuxt/templates.test.js +66 -36
- package/dist/test/nuxt/templates.test.js.map +1 -1
- package/dist/test/react-native/expo.test.js +140 -0
- package/dist/test/react-native/expo.test.js.map +1 -1
- package/dist/test/react-native/git.test.d.ts +1 -0
- package/dist/test/react-native/git.test.js +160 -0
- package/dist/test/react-native/git.test.js.map +1 -0
- package/dist/test/react-router/codemods/client-entry.test.js +38 -5
- package/dist/test/react-router/codemods/client-entry.test.js.map +1 -1
- package/dist/test/react-router/codemods/server-entry.test.js +83 -0
- package/dist/test/react-router/codemods/server-entry.test.js.map +1 -1
- package/dist/test/react-router/codemods/vite.test.js +89 -0
- package/dist/test/react-router/codemods/vite.test.js.map +1 -1
- package/dist/test/react-router/sdk-setup.test.js +98 -6
- package/dist/test/react-router/sdk-setup.test.js.map +1 -1
- package/dist/test/react-router/templates.test.js +50 -38
- package/dist/test/react-router/templates.test.js.map +1 -1
- package/dist/test/remix/build-script.test.d.ts +1 -0
- package/dist/test/remix/build-script.test.js +124 -0
- package/dist/test/remix/build-script.test.js.map +1 -0
- package/dist/test/remix/client-entry.test.js +4 -10
- package/dist/test/remix/client-entry.test.js.map +1 -1
- package/dist/test/run.test.d.ts +1 -0
- package/dist/test/run.test.js +137 -0
- package/dist/test/run.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/vite.test.js +12 -8
- package/dist/test/sourcemaps/tools/vite.test.js.map +1 -1
- package/dist/test/sveltekit/templates.test.js +78 -27
- package/dist/test/sveltekit/templates.test.js.map +1 -1
- package/dist/test/utils/ast-utils.test.js +22 -0
- package/dist/test/utils/ast-utils.test.js.map +1 -1
- package/dist/test/utils/clack/index.test.js +101 -0
- package/dist/test/utils/clack/index.test.js.map +1 -1
- package/dist/test/utils/git.test.js +10 -0
- package/dist/test/utils/git.test.js.map +1 -1
- package/dist/test/utils/line-endings.test.d.ts +1 -0
- package/dist/test/utils/line-endings.test.js +103 -0
- package/dist/test/utils/line-endings.test.js.map +1 -0
- package/package.json +2 -2
- package/dist/src/react-router/codemods/root.d.ts +0 -1
- package/dist/src/react-router/codemods/root.js +0 -171
- package/dist/src/react-router/codemods/root.js.map +0 -1
- package/dist/test/react-router/codemods/root.test.js +0 -178
- package/dist/test/react-router/codemods/root.test.js.map +0 -1
- /package/dist/{test/react-router/codemods/root.test.d.ts → e2e-tests/tests/react-router-instrumentation-api.test.d.ts} +0 -0
|
@@ -32,10 +32,70 @@ exports.XcodeProject = void 0;
|
|
|
32
32
|
const clack = __importStar(require("@clack/prompts"));
|
|
33
33
|
const fs = __importStar(require("node:fs"));
|
|
34
34
|
const path = __importStar(require("node:path"));
|
|
35
|
+
const semver_1 = require("semver");
|
|
35
36
|
const debug_1 = require("../utils/debug");
|
|
36
37
|
const templates = __importStar(require("./templates"));
|
|
37
38
|
const xcode_1 = require("xcode");
|
|
38
39
|
const macos_system_helper_1 = require("./macos-system-helper");
|
|
40
|
+
const XCODE_APPLICATION_PRODUCT_TYPE = 'com.apple.product-type.application';
|
|
41
|
+
const XCODE_UNIT_TEST_PRODUCT_TYPE = 'com.apple.product-type.bundle.unit-test';
|
|
42
|
+
function unquote(value) {
|
|
43
|
+
return typeof value === 'string' ? value.replace(/"/g, '') : '';
|
|
44
|
+
}
|
|
45
|
+
function stripAppExtension(value) {
|
|
46
|
+
return value?.endsWith('.app') ? value.slice(0, -'.app'.length) : value;
|
|
47
|
+
}
|
|
48
|
+
function resolveBuildSettingValue(value, targetName) {
|
|
49
|
+
const resolvedValue = unquote(value)
|
|
50
|
+
.replace(/\$\(TARGET_NAME\)/g, targetName)
|
|
51
|
+
.replace(/\$\{TARGET_NAME\}/g, targetName)
|
|
52
|
+
.trim();
|
|
53
|
+
return resolvedValue && !resolvedValue.includes('$')
|
|
54
|
+
? resolvedValue
|
|
55
|
+
: undefined;
|
|
56
|
+
}
|
|
57
|
+
function uniqueStrings(values) {
|
|
58
|
+
return [...new Set(values.filter(Boolean))];
|
|
59
|
+
}
|
|
60
|
+
function testHostReferencesApplication(testHost, appHostCandidates) {
|
|
61
|
+
const resolvedTestHost = unquote(testHost);
|
|
62
|
+
if (!resolvedTestHost) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const referencesAppBundle = appHostCandidates.bundleNames.some((bundleName) => containsPathSegment(resolvedTestHost, `${bundleName}.app`));
|
|
66
|
+
if (!referencesAppBundle) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return appHostCandidates.executableNames.some((executableName) => containsPathSegment(resolvedTestHost, executableName));
|
|
70
|
+
}
|
|
71
|
+
function containsPathSegment(value, segment) {
|
|
72
|
+
return new RegExp(`(^|/)${escapeRegExp(segment)}(/|$)`).test(value);
|
|
73
|
+
}
|
|
74
|
+
function escapeRegExp(value) {
|
|
75
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
76
|
+
}
|
|
77
|
+
function normalizeSwiftPackageRepositoryURL(value) {
|
|
78
|
+
return unquote(value).replace(/\/+$/, '');
|
|
79
|
+
}
|
|
80
|
+
function shouldUpdatePackageRequirement(existingRequirement, requestedRequirement) {
|
|
81
|
+
if (!existingRequirement || typeof existingRequirement !== 'object') {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
const requirement = existingRequirement;
|
|
85
|
+
if (requirement.kind !== requestedRequirement.kind) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
const existingMinimumVersion = requirement.minimumVersion;
|
|
89
|
+
if (typeof existingMinimumVersion !== 'string') {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
const existingVersion = (0, semver_1.valid)(existingMinimumVersion);
|
|
93
|
+
const requestedVersion = (0, semver_1.valid)(requestedRequirement.minimumVersion);
|
|
94
|
+
if (!existingVersion || !requestedVersion) {
|
|
95
|
+
return existingMinimumVersion !== requestedRequirement.minimumVersion;
|
|
96
|
+
}
|
|
97
|
+
return (0, semver_1.lt)(existingVersion, requestedVersion);
|
|
98
|
+
}
|
|
39
99
|
function setDebugInformationFormatAndSandbox(proj, targetName) {
|
|
40
100
|
const xcObjects = proj.hash.project.objects;
|
|
41
101
|
if (!xcObjects.PBXNativeTarget) {
|
|
@@ -70,106 +130,6 @@ function setDebugInformationFormatAndSandbox(proj, targetName) {
|
|
|
70
130
|
xcObjects.XCBuildConfiguration[buildListConfigId.value] = config;
|
|
71
131
|
}
|
|
72
132
|
}
|
|
73
|
-
function addSentrySPM(proj, targetName) {
|
|
74
|
-
const xcObjects = proj.hash.project.objects;
|
|
75
|
-
const sentryFrameworkUUID = proj.generateUuid();
|
|
76
|
-
const sentrySPMUUID = proj.generateUuid();
|
|
77
|
-
// Check whether xcObjects already have sentry framework
|
|
78
|
-
if (xcObjects.PBXFrameworksBuildPhase) {
|
|
79
|
-
for (const key in xcObjects.PBXFrameworksBuildPhase || {}) {
|
|
80
|
-
const frameworkBuildPhase = xcObjects.PBXFrameworksBuildPhase[key];
|
|
81
|
-
if (key.endsWith('_comment') || typeof frameworkBuildPhase === 'string') {
|
|
82
|
-
// Ignore comments
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
for (const framework of frameworkBuildPhase.files ?? []) {
|
|
86
|
-
// We identify the Sentry framework by the comment "Sentry in Frameworks",
|
|
87
|
-
// which is set by this manager in previous runs.
|
|
88
|
-
if (framework.comment === 'Sentry in Frameworks') {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (!xcObjects.PBXBuildFile) {
|
|
95
|
-
xcObjects.PBXBuildFile = {};
|
|
96
|
-
}
|
|
97
|
-
xcObjects.PBXBuildFile[sentryFrameworkUUID] = {
|
|
98
|
-
isa: 'PBXBuildFile',
|
|
99
|
-
productRef: sentrySPMUUID,
|
|
100
|
-
productRef_comment: 'Sentry',
|
|
101
|
-
};
|
|
102
|
-
xcObjects.PBXBuildFile[`${sentryFrameworkUUID}_comment`] =
|
|
103
|
-
'Sentry in Frameworks';
|
|
104
|
-
if (!xcObjects.PBXFrameworksBuildPhase) {
|
|
105
|
-
xcObjects.PBXFrameworksBuildPhase = {};
|
|
106
|
-
}
|
|
107
|
-
for (const key in xcObjects.PBXFrameworksBuildPhase) {
|
|
108
|
-
const value = xcObjects.PBXFrameworksBuildPhase[key];
|
|
109
|
-
if (key.endsWith('_comment') || typeof value === 'string') {
|
|
110
|
-
// Ignore comments
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
const frameworks = value.files ?? [];
|
|
114
|
-
frameworks.push({
|
|
115
|
-
value: sentryFrameworkUUID,
|
|
116
|
-
comment: 'Sentry in Frameworks',
|
|
117
|
-
});
|
|
118
|
-
value.files = frameworks;
|
|
119
|
-
xcObjects.PBXFrameworksBuildPhase[key] = value;
|
|
120
|
-
}
|
|
121
|
-
if (!xcObjects.PBXNativeTarget) {
|
|
122
|
-
xcObjects.PBXNativeTarget = {};
|
|
123
|
-
}
|
|
124
|
-
const targetKey = Object.keys(xcObjects.PBXNativeTarget || {}).filter((key) => {
|
|
125
|
-
const value = xcObjects.PBXNativeTarget?.[key];
|
|
126
|
-
return (!key.endsWith('_comment') &&
|
|
127
|
-
typeof value !== 'string' &&
|
|
128
|
-
value?.name === targetName);
|
|
129
|
-
})[0];
|
|
130
|
-
const target = xcObjects.PBXNativeTarget[targetKey];
|
|
131
|
-
if (!target.packageProductDependencies) {
|
|
132
|
-
target.packageProductDependencies = [];
|
|
133
|
-
}
|
|
134
|
-
target.packageProductDependencies.push({
|
|
135
|
-
value: sentrySPMUUID,
|
|
136
|
-
comment: 'Sentry',
|
|
137
|
-
});
|
|
138
|
-
const sentrySwiftPackageUUID = proj.generateUuid();
|
|
139
|
-
const xcProject = proj.getFirstProject().firstProject;
|
|
140
|
-
if (!xcProject.packageReferences) {
|
|
141
|
-
xcProject.packageReferences = [];
|
|
142
|
-
}
|
|
143
|
-
xcProject.packageReferences.push({
|
|
144
|
-
value: sentrySwiftPackageUUID,
|
|
145
|
-
comment: 'XCRemoteSwiftPackageReference "sentry-cocoa"',
|
|
146
|
-
});
|
|
147
|
-
if (!xcObjects.XCRemoteSwiftPackageReference) {
|
|
148
|
-
xcObjects.XCRemoteSwiftPackageReference = {};
|
|
149
|
-
}
|
|
150
|
-
xcObjects.XCRemoteSwiftPackageReference[sentrySwiftPackageUUID] = {
|
|
151
|
-
isa: 'XCRemoteSwiftPackageReference',
|
|
152
|
-
repositoryURL: '"https://github.com/getsentry/sentry-cocoa/"',
|
|
153
|
-
requirement: {
|
|
154
|
-
kind: 'upToNextMajorVersion',
|
|
155
|
-
minimumVersion: '8.0.0',
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
xcObjects.XCRemoteSwiftPackageReference[`${sentrySwiftPackageUUID}_comment`] =
|
|
159
|
-
'XCRemoteSwiftPackageReference "sentry-cocoa"';
|
|
160
|
-
if (!xcObjects.XCSwiftPackageProductDependency) {
|
|
161
|
-
xcObjects.XCSwiftPackageProductDependency = {};
|
|
162
|
-
}
|
|
163
|
-
xcObjects.XCSwiftPackageProductDependency[sentrySPMUUID] = {
|
|
164
|
-
isa: 'XCSwiftPackageProductDependency',
|
|
165
|
-
package: sentrySwiftPackageUUID,
|
|
166
|
-
package_comment: 'XCRemoteSwiftPackageReference "sentry-cocoa"',
|
|
167
|
-
productName: 'Sentry',
|
|
168
|
-
};
|
|
169
|
-
xcObjects.XCSwiftPackageProductDependency[`${sentrySPMUUID}_comment`] =
|
|
170
|
-
'Sentry';
|
|
171
|
-
clack.log.step('Added Sentry SPM dependency to your project');
|
|
172
|
-
}
|
|
173
133
|
class XcodeProject {
|
|
174
134
|
/**
|
|
175
135
|
* The directory where the Xcode project is located.
|
|
@@ -208,13 +168,110 @@ class XcodeProject {
|
|
|
208
168
|
const value = targets[key];
|
|
209
169
|
return (!key.endsWith('_comment') &&
|
|
210
170
|
typeof value !== 'string' &&
|
|
211
|
-
value.productType.startsWith(
|
|
171
|
+
unquote(value.productType).startsWith(XCODE_APPLICATION_PRODUCT_TYPE));
|
|
172
|
+
})
|
|
173
|
+
.map((key) => {
|
|
174
|
+
return targets[key].name;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
getUnitTestTargetNames() {
|
|
178
|
+
const targets = this.objects.PBXNativeTarget ?? {};
|
|
179
|
+
return Object.keys(targets)
|
|
180
|
+
.filter((key) => {
|
|
181
|
+
const value = targets[key];
|
|
182
|
+
return this.isUnitTestTargetEntry(key, value);
|
|
212
183
|
})
|
|
213
184
|
.map((key) => {
|
|
214
185
|
return targets[key].name;
|
|
215
186
|
});
|
|
216
187
|
}
|
|
217
|
-
|
|
188
|
+
getHostedUnitTestTargetNames() {
|
|
189
|
+
const targets = this.objects.PBXNativeTarget ?? {};
|
|
190
|
+
return Object.keys(targets)
|
|
191
|
+
.filter((key) => {
|
|
192
|
+
const value = targets[key];
|
|
193
|
+
return (this.isUnitTestTargetEntry(key, value) &&
|
|
194
|
+
this.getTargetBuildSettings(value).some((buildSettings) => Boolean(unquote(buildSettings.TEST_HOST).trim())));
|
|
195
|
+
})
|
|
196
|
+
.map((key) => {
|
|
197
|
+
return targets[key].name;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
getHostedUnitTestTargetNamesForApplicationTarget(appTargetName) {
|
|
201
|
+
const appTarget = this.findNativeTargetByName(appTargetName);
|
|
202
|
+
if (!appTarget) {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
const appHostCandidates = this.getApplicationHostCandidates(appTarget);
|
|
206
|
+
const targets = this.objects.PBXNativeTarget ?? {};
|
|
207
|
+
return Object.keys(targets)
|
|
208
|
+
.filter((key) => {
|
|
209
|
+
const value = targets[key];
|
|
210
|
+
return (!key.endsWith('_comment') &&
|
|
211
|
+
typeof value !== 'string' &&
|
|
212
|
+
unquote(value.productType) === XCODE_UNIT_TEST_PRODUCT_TYPE &&
|
|
213
|
+
this.getTargetBuildSettings(value).some((buildSettings) => testHostReferencesApplication(buildSettings.TEST_HOST, appHostCandidates)));
|
|
214
|
+
})
|
|
215
|
+
.map((key) => {
|
|
216
|
+
return targets[key].name;
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
getBundleIdentifierForTarget(targetName) {
|
|
220
|
+
const target = this.findNativeTargetByName(targetName);
|
|
221
|
+
if (!target) {
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
return this.getTargetBuildSettings(target.obj)
|
|
225
|
+
.map((buildSettings) => {
|
|
226
|
+
return unquote(buildSettings.PRODUCT_BUNDLE_IDENTIFIER);
|
|
227
|
+
})
|
|
228
|
+
.find(Boolean);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Idempotently links a Swift package product to one target dependency list
|
|
232
|
+
* and Frameworks build phase. Returns whether the pbxproj graph changed and
|
|
233
|
+
* whether the product is linked after the operation.
|
|
234
|
+
*/
|
|
235
|
+
ensureSwiftPackageProductLinked(targetName, product) {
|
|
236
|
+
const target = this.findNativeTargetByName(targetName);
|
|
237
|
+
if (!target) {
|
|
238
|
+
(0, debug_1.debug)(`Target not found: ${targetName}`);
|
|
239
|
+
return { changed: false, linked: false };
|
|
240
|
+
}
|
|
241
|
+
const frameworksBuildPhase = this.findFrameworksBuildPhaseInTarget(target.obj);
|
|
242
|
+
if (!frameworksBuildPhase) {
|
|
243
|
+
(0, debug_1.debug)(`Frameworks build phase not found for target: ${targetName}`);
|
|
244
|
+
return { changed: false, linked: false };
|
|
245
|
+
}
|
|
246
|
+
let changed = false;
|
|
247
|
+
// Ensure the remote Swift package object exists.
|
|
248
|
+
const packageReference = this.ensureSwiftPackageReference(product.package);
|
|
249
|
+
changed = packageReference.changed || changed;
|
|
250
|
+
// Attach the Swift package object to the root Xcode project.
|
|
251
|
+
changed =
|
|
252
|
+
this.ensureProjectSwiftPackageReference(packageReference.packageRefId, product.package.commentName) || changed;
|
|
253
|
+
// Ensure the package product dependency object exists.
|
|
254
|
+
const productDependency = this.ensureSwiftPackageProductDependency(packageReference.packageRefId, product);
|
|
255
|
+
changed = productDependency.changed || changed;
|
|
256
|
+
if (!target.obj.packageProductDependencies) {
|
|
257
|
+
target.obj.packageProductDependencies = [];
|
|
258
|
+
}
|
|
259
|
+
// Attach the package product dependency to the selected target.
|
|
260
|
+
if (!target.obj.packageProductDependencies.some((dependency) => {
|
|
261
|
+
return dependency.value === productDependency.productDependencyId;
|
|
262
|
+
})) {
|
|
263
|
+
target.obj.packageProductDependencies.push({
|
|
264
|
+
value: productDependency.productDependencyId,
|
|
265
|
+
comment: product.productName,
|
|
266
|
+
});
|
|
267
|
+
changed = true;
|
|
268
|
+
}
|
|
269
|
+
// Link the package product in the target Frameworks build phase.
|
|
270
|
+
changed =
|
|
271
|
+
this.ensureFrameworksBuildFile(frameworksBuildPhase, productDependency.productDependencyId, product) || changed;
|
|
272
|
+
return { changed, linked: true };
|
|
273
|
+
}
|
|
274
|
+
updateXcodeProject(sentryProject, target, swiftPackageProduct, uploadSource = true) {
|
|
218
275
|
this.addUploadSymbolsScript({
|
|
219
276
|
sentryProject,
|
|
220
277
|
targetName: target,
|
|
@@ -223,11 +280,15 @@ class XcodeProject {
|
|
|
223
280
|
if (uploadSource) {
|
|
224
281
|
setDebugInformationFormatAndSandbox(this.project, target);
|
|
225
282
|
}
|
|
226
|
-
if (
|
|
227
|
-
|
|
283
|
+
if (swiftPackageProduct &&
|
|
284
|
+
!(swiftPackageProduct.existingFrameworkComment &&
|
|
285
|
+
this.hasFrameworkBuildFileCommentInTarget(target, swiftPackageProduct.existingFrameworkComment))) {
|
|
286
|
+
const result = this.ensureSwiftPackageProductLinked(target, swiftPackageProduct.product);
|
|
287
|
+
if (result.changed && swiftPackageProduct.successMessage) {
|
|
288
|
+
clack.log.step(swiftPackageProduct.successMessage);
|
|
289
|
+
}
|
|
228
290
|
}
|
|
229
|
-
|
|
230
|
-
fs.writeFileSync(this.pbxprojPath, newContent);
|
|
291
|
+
this.write();
|
|
231
292
|
}
|
|
232
293
|
addUploadSymbolsScript({ sentryProject, targetName, uploadSource, }) {
|
|
233
294
|
const xcObjects = this.project.hash.project.objects;
|
|
@@ -306,6 +367,87 @@ class XcodeProject {
|
|
|
306
367
|
clack.log.step(`Added Sentry upload script to "${targetName}" build phase`);
|
|
307
368
|
}
|
|
308
369
|
}
|
|
370
|
+
write() {
|
|
371
|
+
const newContent = this.project.writeSync();
|
|
372
|
+
fs.writeFileSync(this.pbxprojPath, newContent);
|
|
373
|
+
}
|
|
374
|
+
getSynchronizedRootGroupPathsForTarget(targetName) {
|
|
375
|
+
const nativeTarget = this.findNativeTargetByName(targetName);
|
|
376
|
+
if (!nativeTarget) {
|
|
377
|
+
return [];
|
|
378
|
+
}
|
|
379
|
+
return (nativeTarget.obj.fileSystemSynchronizedGroups ?? []).reduce((groupPaths, group) => {
|
|
380
|
+
const groupObj = this.objects.PBXFileSystemSynchronizedRootGroup?.[group.value];
|
|
381
|
+
if (!groupObj || typeof groupObj !== 'object') {
|
|
382
|
+
return groupPaths;
|
|
383
|
+
}
|
|
384
|
+
const groupPath = this.resolveAbsolutePathOfSynchronizedRootGroup({
|
|
385
|
+
id: group.value,
|
|
386
|
+
obj: groupObj,
|
|
387
|
+
});
|
|
388
|
+
if (!groupPath) {
|
|
389
|
+
return groupPaths;
|
|
390
|
+
}
|
|
391
|
+
return groupPaths.concat(groupPath);
|
|
392
|
+
}, new Array());
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Ensures a Swift file is compiled by a target, either through an Xcode
|
|
396
|
+
* synchronized root group or an explicit Sources build phase entry.
|
|
397
|
+
*/
|
|
398
|
+
addSwiftSourceFileToTarget(args) {
|
|
399
|
+
const nativeTarget = this.findNativeTargetByName(args.targetName);
|
|
400
|
+
const defaultResult = { changed: false, included: false };
|
|
401
|
+
if (!nativeTarget) {
|
|
402
|
+
(0, debug_1.debug)(`Target not found: ${args.targetName}`);
|
|
403
|
+
return defaultResult;
|
|
404
|
+
}
|
|
405
|
+
const absoluteFilePath = args.filePath;
|
|
406
|
+
if (this.isFileIncludedBySynchronizedRootGroup(nativeTarget, absoluteFilePath)) {
|
|
407
|
+
return {
|
|
408
|
+
changed: false,
|
|
409
|
+
included: true,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
const sourceBuildPhase = this.findSourceBuildPhaseInTarget(nativeTarget.obj);
|
|
413
|
+
if (!sourceBuildPhase) {
|
|
414
|
+
(0, debug_1.debug)(`Sources build phase not found for target: ${args.targetName}`);
|
|
415
|
+
return defaultResult;
|
|
416
|
+
}
|
|
417
|
+
const fileReference = this.ensureSwiftFileReference(absoluteFilePath);
|
|
418
|
+
const sourceBuildPhaseFiles = sourceBuildPhase.obj.files ?? [];
|
|
419
|
+
const existingBuildFileReference = sourceBuildPhaseFiles.find((file) => {
|
|
420
|
+
const buildFile = this.objects.PBXBuildFile?.[file.value];
|
|
421
|
+
return (buildFile &&
|
|
422
|
+
typeof buildFile !== 'string' &&
|
|
423
|
+
buildFile.fileRef === fileReference.fileReferenceId);
|
|
424
|
+
});
|
|
425
|
+
if (existingBuildFileReference) {
|
|
426
|
+
return {
|
|
427
|
+
changed: fileReference.changed,
|
|
428
|
+
included: true,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
if (!this.objects.PBXBuildFile) {
|
|
432
|
+
this.objects.PBXBuildFile = {};
|
|
433
|
+
}
|
|
434
|
+
const buildFileId = this.project.generateUuid();
|
|
435
|
+
const fileName = path.basename(absoluteFilePath);
|
|
436
|
+
this.objects.PBXBuildFile[buildFileId] = {
|
|
437
|
+
isa: 'PBXBuildFile',
|
|
438
|
+
fileRef: fileReference.fileReferenceId,
|
|
439
|
+
fileRef_comment: fileName,
|
|
440
|
+
};
|
|
441
|
+
this.objects.PBXBuildFile[`${buildFileId}_comment`] = `${fileName} in Sources`;
|
|
442
|
+
sourceBuildPhase.obj.files = [
|
|
443
|
+
...sourceBuildPhaseFiles,
|
|
444
|
+
{
|
|
445
|
+
value: buildFileId,
|
|
446
|
+
comment: `${fileName} in Sources`,
|
|
447
|
+
},
|
|
448
|
+
];
|
|
449
|
+
return { changed: true, included: true };
|
|
450
|
+
}
|
|
309
451
|
/**
|
|
310
452
|
* Retrieves all source files associated with a specific target in the Xcode project.
|
|
311
453
|
* This is used to find files where we can inject Sentry initialization code.
|
|
@@ -343,6 +485,265 @@ class XcodeProject {
|
|
|
343
485
|
(0, debug_1.debug)(`Found ${filesInSynchronizedRootGroups.length} files in synchronized root groups for target: ${targetName}`);
|
|
344
486
|
return [...filesInBuildPhase, ...filesInSynchronizedRootGroups];
|
|
345
487
|
}
|
|
488
|
+
isUnitTestTargetEntry(key, value) {
|
|
489
|
+
return (!key.endsWith('_comment') &&
|
|
490
|
+
typeof value !== 'string' &&
|
|
491
|
+
value !== undefined &&
|
|
492
|
+
unquote(value.productType) === XCODE_UNIT_TEST_PRODUCT_TYPE);
|
|
493
|
+
}
|
|
494
|
+
getTargetBuildSettings(target) {
|
|
495
|
+
const buildConfigurationListId = target.buildConfigurationList;
|
|
496
|
+
if (!buildConfigurationListId) {
|
|
497
|
+
return [];
|
|
498
|
+
}
|
|
499
|
+
const configurationList = this.objects.XCConfigurationList?.[buildConfigurationListId];
|
|
500
|
+
if (!configurationList || typeof configurationList === 'string') {
|
|
501
|
+
return [];
|
|
502
|
+
}
|
|
503
|
+
return (configurationList.buildConfigurations ?? []).reduce((buildSettings, buildConfiguration) => {
|
|
504
|
+
const configuration = this.objects.XCBuildConfiguration?.[buildConfiguration.value];
|
|
505
|
+
if (!configuration || typeof configuration === 'string') {
|
|
506
|
+
return buildSettings;
|
|
507
|
+
}
|
|
508
|
+
return buildSettings.concat(configuration.buildSettings ?? {});
|
|
509
|
+
}, new Array());
|
|
510
|
+
}
|
|
511
|
+
getApplicationHostCandidates(target) {
|
|
512
|
+
const buildSettings = this.getTargetBuildSettings(target.obj);
|
|
513
|
+
const productReferencePath = this.getProductReferencePath(target.obj);
|
|
514
|
+
const productReferenceName = stripAppExtension(productReferencePath);
|
|
515
|
+
const targetProductName = resolveBuildSettingValue(target.obj.productName, target.obj.name);
|
|
516
|
+
const buildSettingProductNames = buildSettings.flatMap((settings) => [
|
|
517
|
+
resolveBuildSettingValue(settings.PRODUCT_NAME, target.obj.name),
|
|
518
|
+
stripAppExtension(resolveBuildSettingValue(settings.FULL_PRODUCT_NAME, target.obj.name)),
|
|
519
|
+
stripAppExtension(resolveBuildSettingValue(settings.WRAPPER_NAME, target.obj.name)),
|
|
520
|
+
]);
|
|
521
|
+
const buildSettingExecutableNames = buildSettings.map((settings) => resolveBuildSettingValue(settings.EXECUTABLE_NAME, target.obj.name));
|
|
522
|
+
return {
|
|
523
|
+
bundleNames: uniqueStrings([
|
|
524
|
+
target.obj.name,
|
|
525
|
+
targetProductName,
|
|
526
|
+
productReferenceName,
|
|
527
|
+
...buildSettingProductNames,
|
|
528
|
+
]),
|
|
529
|
+
executableNames: uniqueStrings([
|
|
530
|
+
target.obj.name,
|
|
531
|
+
targetProductName,
|
|
532
|
+
productReferenceName,
|
|
533
|
+
...buildSettingExecutableNames,
|
|
534
|
+
]),
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
getProductReferencePath(target) {
|
|
538
|
+
if (!target.productReference) {
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
541
|
+
const productReference = this.objects.PBXFileReference?.[target.productReference];
|
|
542
|
+
if (!productReference || typeof productReference === 'string') {
|
|
543
|
+
return undefined;
|
|
544
|
+
}
|
|
545
|
+
return unquote(productReference.path);
|
|
546
|
+
}
|
|
547
|
+
hasFrameworkBuildFileCommentInTarget(targetName, comment) {
|
|
548
|
+
const target = this.findNativeTargetByName(targetName);
|
|
549
|
+
if (!target) {
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
const frameworksBuildPhase = this.findFrameworksBuildPhaseInTarget(target.obj);
|
|
553
|
+
return (frameworksBuildPhase?.files ?? []).some((framework) => {
|
|
554
|
+
return framework.comment === comment;
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
ensureSwiftPackageReference(packageSpec) {
|
|
558
|
+
if (!this.objects.XCRemoteSwiftPackageReference) {
|
|
559
|
+
this.objects.XCRemoteSwiftPackageReference = {};
|
|
560
|
+
}
|
|
561
|
+
const packageReferences = this.objects
|
|
562
|
+
.XCRemoteSwiftPackageReference;
|
|
563
|
+
const requestedRepositoryURL = normalizeSwiftPackageRepositoryURL(packageSpec.repositoryURL);
|
|
564
|
+
const existingPackageReference = Object.entries(packageReferences).find(([id, value]) => {
|
|
565
|
+
if (id.endsWith('_comment') || typeof value !== 'object') {
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
const packageReference = value;
|
|
569
|
+
return (normalizeSwiftPackageRepositoryURL(packageReference.repositoryURL) ===
|
|
570
|
+
requestedRepositoryURL);
|
|
571
|
+
});
|
|
572
|
+
if (existingPackageReference) {
|
|
573
|
+
const packageReference = existingPackageReference[1];
|
|
574
|
+
if (shouldUpdatePackageRequirement(packageReference.requirement, packageSpec.requirement)) {
|
|
575
|
+
packageReference.requirement = packageSpec.requirement;
|
|
576
|
+
return { packageRefId: existingPackageReference[0], changed: true };
|
|
577
|
+
}
|
|
578
|
+
return { packageRefId: existingPackageReference[0], changed: false };
|
|
579
|
+
}
|
|
580
|
+
const packageRefId = this.project.generateUuid();
|
|
581
|
+
packageReferences[packageRefId] = {
|
|
582
|
+
isa: 'XCRemoteSwiftPackageReference',
|
|
583
|
+
repositoryURL: `"${packageSpec.repositoryURL}"`,
|
|
584
|
+
requirement: packageSpec.requirement,
|
|
585
|
+
};
|
|
586
|
+
packageReferences[`${packageRefId}_comment`] =
|
|
587
|
+
this.swiftPackageReferenceComment(packageSpec.commentName);
|
|
588
|
+
return { packageRefId, changed: true };
|
|
589
|
+
}
|
|
590
|
+
ensureProjectSwiftPackageReference(packageRefId, commentName) {
|
|
591
|
+
const xcodeProject = this.project.getFirstProject().firstProject;
|
|
592
|
+
if (!xcodeProject.packageReferences) {
|
|
593
|
+
xcodeProject.packageReferences = [];
|
|
594
|
+
}
|
|
595
|
+
if (xcodeProject.packageReferences.some((packageReference) => {
|
|
596
|
+
return packageReference.value === packageRefId;
|
|
597
|
+
})) {
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
xcodeProject.packageReferences.push({
|
|
601
|
+
value: packageRefId,
|
|
602
|
+
comment: this.swiftPackageReferenceComment(commentName),
|
|
603
|
+
});
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
606
|
+
ensureSwiftPackageProductDependency(packageRefId, product) {
|
|
607
|
+
if (!this.objects.XCSwiftPackageProductDependency) {
|
|
608
|
+
this.objects.XCSwiftPackageProductDependency = {};
|
|
609
|
+
}
|
|
610
|
+
const productDependencies = this.objects
|
|
611
|
+
.XCSwiftPackageProductDependency;
|
|
612
|
+
const existingProductDependency = Object.entries(productDependencies).find(([id, value]) => {
|
|
613
|
+
if (id.endsWith('_comment') || typeof value !== 'object') {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
const productDependency = value;
|
|
617
|
+
return (productDependency.package === packageRefId &&
|
|
618
|
+
unquote(productDependency.productName) === product.productName);
|
|
619
|
+
});
|
|
620
|
+
if (existingProductDependency) {
|
|
621
|
+
return {
|
|
622
|
+
productDependencyId: existingProductDependency[0],
|
|
623
|
+
changed: false,
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
const productDependencyId = this.project.generateUuid();
|
|
627
|
+
productDependencies[productDependencyId] = {
|
|
628
|
+
isa: 'XCSwiftPackageProductDependency',
|
|
629
|
+
package: packageRefId,
|
|
630
|
+
package_comment: this.swiftPackageReferenceComment(product.package.commentName),
|
|
631
|
+
productName: product.productName,
|
|
632
|
+
};
|
|
633
|
+
productDependencies[`${productDependencyId}_comment`] = product.productName;
|
|
634
|
+
return { productDependencyId, changed: true };
|
|
635
|
+
}
|
|
636
|
+
ensureFrameworksBuildFile(frameworksBuildPhase, productDependencyId, product) {
|
|
637
|
+
if (!this.objects.PBXBuildFile) {
|
|
638
|
+
this.objects.PBXBuildFile = {};
|
|
639
|
+
}
|
|
640
|
+
const existingFrameworkEntry = (frameworksBuildPhase.files ?? []).find((framework) => {
|
|
641
|
+
const buildFile = this.objects.PBXBuildFile?.[framework.value];
|
|
642
|
+
return (buildFile &&
|
|
643
|
+
typeof buildFile !== 'string' &&
|
|
644
|
+
buildFile.productRef === productDependencyId);
|
|
645
|
+
});
|
|
646
|
+
if (existingFrameworkEntry) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
const buildFileId = this.project.generateUuid();
|
|
650
|
+
this.objects.PBXBuildFile[buildFileId] = {
|
|
651
|
+
isa: 'PBXBuildFile',
|
|
652
|
+
productRef: productDependencyId,
|
|
653
|
+
productRef_comment: product.productName,
|
|
654
|
+
};
|
|
655
|
+
this.objects.PBXBuildFile[`${buildFileId}_comment`] = `${product.productName} in Frameworks`;
|
|
656
|
+
if (!frameworksBuildPhase.files) {
|
|
657
|
+
frameworksBuildPhase.files = [];
|
|
658
|
+
}
|
|
659
|
+
frameworksBuildPhase.files.push({
|
|
660
|
+
value: buildFileId,
|
|
661
|
+
comment: `${product.productName} in Frameworks`,
|
|
662
|
+
});
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
665
|
+
findFrameworksBuildPhaseInTarget(target) {
|
|
666
|
+
for (const buildPhaseReference of target.buildPhases ?? []) {
|
|
667
|
+
const buildPhase = this.objects.PBXFrameworksBuildPhase?.[buildPhaseReference.value];
|
|
668
|
+
if (buildPhase && typeof buildPhase !== 'string') {
|
|
669
|
+
return buildPhase;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return undefined;
|
|
673
|
+
}
|
|
674
|
+
swiftPackageReferenceComment(commentName) {
|
|
675
|
+
return `XCRemoteSwiftPackageReference "${commentName}"`;
|
|
676
|
+
}
|
|
677
|
+
isFileIncludedBySynchronizedRootGroup(nativeTarget, absoluteFilePath) {
|
|
678
|
+
return this.findFilesInSynchronizedRootGroups(nativeTarget).some((filePath) => filePath === absoluteFilePath);
|
|
679
|
+
}
|
|
680
|
+
ensureSwiftFileReference(absoluteFilePath) {
|
|
681
|
+
if (!this.objects.PBXFileReference) {
|
|
682
|
+
this.objects.PBXFileReference = {};
|
|
683
|
+
}
|
|
684
|
+
const existingFileReference = Object.entries(this.objects.PBXFileReference).find(([id, fileReference]) => {
|
|
685
|
+
if (id.endsWith('_comment') || typeof fileReference !== 'object') {
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
const resolvedFilePath = this.resolveAbsolutePathOfFileReference({
|
|
689
|
+
id,
|
|
690
|
+
obj: fileReference,
|
|
691
|
+
});
|
|
692
|
+
return resolvedFilePath === absoluteFilePath;
|
|
693
|
+
});
|
|
694
|
+
if (existingFileReference) {
|
|
695
|
+
return { fileReferenceId: existingFileReference[0], changed: false };
|
|
696
|
+
}
|
|
697
|
+
const fileReferenceId = this.project.generateUuid();
|
|
698
|
+
const fileName = path.basename(absoluteFilePath);
|
|
699
|
+
const relativePath = path.relative(this.baseDir, absoluteFilePath);
|
|
700
|
+
this.objects.PBXFileReference[fileReferenceId] = {
|
|
701
|
+
isa: 'PBXFileReference',
|
|
702
|
+
lastKnownFileType: 'sourcecode.swift',
|
|
703
|
+
path: relativePath,
|
|
704
|
+
sourceTree: 'SOURCE_ROOT',
|
|
705
|
+
};
|
|
706
|
+
this.objects.PBXFileReference[`${fileReferenceId}_comment`] = fileName;
|
|
707
|
+
this.addFileReferenceToBestGroup(fileReferenceId, fileName, absoluteFilePath);
|
|
708
|
+
return { fileReferenceId, changed: true };
|
|
709
|
+
}
|
|
710
|
+
addFileReferenceToBestGroup(fileReferenceId, fileName, absoluteFilePath) {
|
|
711
|
+
const parentDirectory = path.dirname(absoluteFilePath);
|
|
712
|
+
const parentGroup = this.groups.find((group) => {
|
|
713
|
+
const groupPath = this.resolveAbsolutePathOfGroup(group);
|
|
714
|
+
return groupPath === parentDirectory;
|
|
715
|
+
}) ?? this.mainGroup;
|
|
716
|
+
if (!parentGroup) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
if (!parentGroup.obj.children) {
|
|
720
|
+
parentGroup.obj.children = [];
|
|
721
|
+
}
|
|
722
|
+
if (parentGroup.obj.children.some((child) => child.value === fileReferenceId)) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
parentGroup.obj.children.push({
|
|
726
|
+
value: fileReferenceId,
|
|
727
|
+
comment: fileName,
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
get mainGroup() {
|
|
731
|
+
const project = Object.entries(this.objects.PBXProject ?? {}).find(([id, candidate]) => {
|
|
732
|
+
return !id.endsWith('_comment') && typeof candidate === 'object';
|
|
733
|
+
})?.[1];
|
|
734
|
+
if (!project || typeof project !== 'object') {
|
|
735
|
+
return undefined;
|
|
736
|
+
}
|
|
737
|
+
const mainGroupId = project.mainGroup;
|
|
738
|
+
if (!mainGroupId) {
|
|
739
|
+
return undefined;
|
|
740
|
+
}
|
|
741
|
+
const mainGroup = this.objects.PBXGroup?.[mainGroupId];
|
|
742
|
+
if (!mainGroup || typeof mainGroup !== 'object') {
|
|
743
|
+
return undefined;
|
|
744
|
+
}
|
|
745
|
+
return { id: mainGroupId, obj: mainGroup };
|
|
746
|
+
}
|
|
346
747
|
// ================================ TARGET HELPERS ================================
|
|
347
748
|
/**
|
|
348
749
|
* Finds a native target by name.
|