UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

947 lines • 54 kB
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.IOSProjectService = exports.VisionSimulatorPlatformSdkName = exports.VisionDevicePlatformSdkName = exports.SimulatorPlatformSdkName = exports.DevicePlatformSdkName = void 0;
const path = require("path");
const shell = require("shelljs");
const _ = require("lodash");
const constants = require("../constants");
const constants_1 = require("../common/constants");
const helpers = require("../common/helpers");
const helpers_1 = require("../common/helpers");
const projectServiceBaseLib = require("./platform-project-service-base");
const plist_merge_patch_1 = require("plist-merge-patch");
const os_1 = require("os");
const plist = require("plist");
const fastGlob = require("fast-glob");
const constants_2 = require("../constants");
const helpers_2 = require("../common/helpers");
const yok_1 = require("../common/yok");
exports.DevicePlatformSdkName = "iphoneos";
exports.SimulatorPlatformSdkName = "iphonesimulator";
exports.VisionDevicePlatformSdkName = "xros";
exports.VisionSimulatorPlatformSdkName = "xrsimulator";
const FRAMEWORK_EXTENSIONS = [".framework", ".xcframework"];
const getPlatformSdkName = (buildData) => {
    const forDevice = !buildData || buildData.buildForDevice || buildData.buildForAppStore;
    const isvisionOS = yok_1.injector
        .resolve("devicePlatformsConstants")
        .isvisionOS(buildData.platform);
    if (isvisionOS) {
        return forDevice
            ? exports.VisionDevicePlatformSdkName
            : exports.VisionSimulatorPlatformSdkName;
    }
    return forDevice ? exports.DevicePlatformSdkName : exports.SimulatorPlatformSdkName;
};
const getConfigurationName = (release) => {
    return release ? constants_1.Configurations.Release : constants_1.Configurations.Debug;
};
class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase {
    constructor($fs, $options, $childProcess, $cocoapodsService, $errors, $logger, $injector, $projectDataService, $devicePlatformsConstants, $hostInfo, $xcprojService, $iOSProvisionService, $iOSSigningService, $pbxprojDomXcode, $xcode, $iOSEntitlementsService, $platformEnvironmentRequirements, $plistParser, $xcconfigService, $xcodebuildService, $iOSExtensionsService, $iOSWatchAppService, $iOSNativeTargetService, $sysInfo, $tempService, $spmService, $mobileHelper, $projectConfigService) {
        super($fs, $projectDataService);
        this.$options = $options;
        this.$childProcess = $childProcess;
        this.$cocoapodsService = $cocoapodsService;
        this.$errors = $errors;
        this.$logger = $logger;
        this.$injector = $injector;
        this.$devicePlatformsConstants = $devicePlatformsConstants;
        this.$hostInfo = $hostInfo;
        this.$xcprojService = $xcprojService;
        this.$iOSProvisionService = $iOSProvisionService;
        this.$iOSSigningService = $iOSSigningService;
        this.$pbxprojDomXcode = $pbxprojDomXcode;
        this.$xcode = $xcode;
        this.$iOSEntitlementsService = $iOSEntitlementsService;
        this.$platformEnvironmentRequirements = $platformEnvironmentRequirements;
        this.$plistParser = $plistParser;
        this.$xcconfigService = $xcconfigService;
        this.$xcodebuildService = $xcodebuildService;
        this.$iOSExtensionsService = $iOSExtensionsService;
        this.$iOSWatchAppService = $iOSWatchAppService;
        this.$iOSNativeTargetService = $iOSNativeTargetService;
        this.$sysInfo = $sysInfo;
        this.$tempService = $tempService;
        this.$spmService = $spmService;
        this.$mobileHelper = $mobileHelper;
        this.$projectConfigService = $projectConfigService;
        this._platformsDirCache = null;
        this._platformData = null;
    }
    getPlatformData(projectData) {
        var _a;
        if (!projectData && !this._platformData) {
            throw new Error("First call of getPlatformData without providing projectData.");
        }
        if (projectData &&
            projectData.platformsDir &&
            this._platformsDirCache !== projectData.platformsDir) {
            const platform = this.$mobileHelper.normalizePlatformName((_a = this.$options.platformOverride) !== null && _a !== void 0 ? _a : this.$devicePlatformsConstants.iOS);
            const projectRoot = this.$options.hostProjectPath
                ? this.$options.hostProjectPath
                : path.join(projectData.platformsDir, platform.toLowerCase());
            const runtimePackage = this.$projectDataService.getRuntimePackage(projectData.projectDir, platform.toLowerCase());
            this._platformData = {
                frameworkPackageName: runtimePackage.name,
                normalizedPlatformName: platform,
                platformNameLowerCase: platform.toLowerCase(),
                appDestinationDirectoryPath: path.join(projectRoot, projectData.projectName),
                platformProjectService: this,
                projectRoot: projectRoot,
                getBuildOutputPath: (options) => {
                    const config = getConfigurationName(!options || options.release);
                    return path.join(projectRoot, constants.BUILD_DIR, `${config}-${getPlatformSdkName(options)}`);
                },
                getValidBuildOutputData: (buildOptions) => {
                    const forDevice = !buildOptions ||
                        !!buildOptions.buildForDevice ||
                        !!buildOptions.buildForAppStore;
                    if (forDevice) {
                        const ipaFileName = _.find(this.$fs.readDirectory(this._platformData.getBuildOutputPath(buildOptions)), (entry) => path.extname(entry) === ".ipa");
                        return {
                            packageNames: [ipaFileName, `${projectData.projectName}.ipa`],
                        };
                    }
                    return {
                        packageNames: [
                            `${projectData.projectName}.app`,
                            `${projectData.projectName}.zip`,
                        ],
                    };
                },
                frameworkDirectoriesExtensions: FRAMEWORK_EXTENSIONS,
                frameworkDirectoriesNames: [
                    "Metadata",
                    "metadataGenerator",
                    "NativeScript",
                    "internal",
                ],
                targetedOS: ["darwin"],
                configurationFileName: constants.INFO_PLIST_FILE_NAME,
                configurationFilePath: path.join(projectRoot, projectData.projectName, projectData.projectName + `-${constants.INFO_PLIST_FILE_NAME}`),
                relativeToFrameworkConfigurationFilePath: path.join("__PROJECT_NAME__", "__PROJECT_NAME__-Info.plist"),
                fastLivesyncFileExtensions: [
                    ".tiff",
                    ".tif",
                    ".jpg",
                    "jpeg",
                    "gif",
                    ".png",
                    ".bmp",
                    ".BMPf",
                    ".ico",
                    ".cur",
                    ".xbm",
                ], // https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/
            };
        }
        return this._platformData;
    }
    async validateOptions(projectId, provision, teamId) {
        if (provision && teamId) {
            this.$errors.fail("The options --provision and --teamId are mutually exclusive.");
        }
        if (provision === true) {
            await this.$iOSProvisionService.listProvisions(projectId);
            this.$errors.fail("Please provide provisioning profile uuid or name with the --provision option.");
        }
        if (teamId === true) {
            await this.$iOSProvisionService.listTeams();
            this.$errors.fail("Please provide team id or team name with the --teamId options.");
        }
        return true;
    }
    getAppResourcesDestinationDirectoryPath(projectData) {
        return path.join(this.getPlatformData(projectData).projectRoot, projectData.projectName, "Resources");
    }
    async validate(projectData, options, notConfiguredEnvOptions) {
        if (!this.$hostInfo.isDarwin) {
            return;
        }
        const checkEnvironmentRequirementsOutput = await this.$platformEnvironmentRequirements.checkEnvironmentRequirements({
            platform: this.getPlatformData(projectData).normalizedPlatformName,
            projectDir: projectData.projectDir,
            options,
            notConfiguredEnvOptions,
        });
        if (checkEnvironmentRequirementsOutput &&
            checkEnvironmentRequirementsOutput.canExecute) {
            const xcodeWarning = await this.$sysInfo.getXcodeWarning();
            if (xcodeWarning) {
                this.$logger.warn(xcodeWarning);
            }
        }
        return {
            checkEnvironmentRequirementsOutput,
        };
    }
    async createProject(frameworkDir, frameworkVersion, projectData) {
        this.$fs.ensureDirectoryExists(path.join(this.getPlatformData(projectData).projectRoot, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER));
        shell.cp("-R", path.join(frameworkDir, "*"), this.getPlatformData(projectData).projectRoot);
    }
    //TODO: plamen5kov: revisit this method, might have unnecessary/obsolete logic
    async interpolateData(projectData) {
        const projectRootFilePath = path.join(this.getPlatformData(projectData).projectRoot, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER);
        // Starting with NativeScript for iOS 1.6.0, the project Info.plist file resides not in the platform project,
        // but in the hello-world app template as a platform specific resource.
        if (this.$fs.exists(path.join(projectRootFilePath, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER + "-Info.plist"))) {
            this.replaceFileName("-Info.plist", projectRootFilePath, projectData);
        }
        this.replaceFileName("-Prefix.pch", projectRootFilePath, projectData);
        if (this.$fs.exists(path.join(projectRootFilePath, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER + ".entitlements"))) {
            this.replaceFileName(".entitlements", projectRootFilePath, projectData);
        }
        const xcschemeDirPath = path.join(this.getPlatformData(projectData).projectRoot, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER +
            constants_2.IosProjectConstants.XcodeProjExtName, "xcshareddata/xcschemes");
        const xcschemeFilePath = path.join(xcschemeDirPath, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER +
            constants_2.IosProjectConstants.XcodeSchemeExtName);
        if (this.$fs.exists(xcschemeFilePath)) {
            this.$logger.trace("Found shared scheme at xcschemeFilePath, renaming to match project name.");
            this.$logger.trace("Checkpoint 0");
            this.replaceFileContent(xcschemeFilePath, projectData);
            this.$logger.trace("Checkpoint 1");
            this.replaceFileName(constants_2.IosProjectConstants.XcodeSchemeExtName, xcschemeDirPath, projectData);
            this.$logger.trace("Checkpoint 2");
        }
        else {
            this.$logger.trace("Copying xcscheme from template not found at " + xcschemeFilePath);
        }
        this.replaceFileName(constants_2.IosProjectConstants.XcodeProjExtName, this.getPlatformData(projectData).projectRoot, projectData);
        const pbxprojFilePath = this.getPbxProjPath(projectData);
        this.replaceFileContent(pbxprojFilePath, projectData);
        const internalDirPath = path.join(projectRootFilePath, "..", "internal");
        const xcframeworksFilePath = path.join(internalDirPath, "XCFrameworks.zip");
        if (this.$fs.exists(xcframeworksFilePath)) {
            await this.$fs.unzip(xcframeworksFilePath, internalDirPath);
            this.$fs.deleteFile(xcframeworksFilePath);
        }
    }
    interpolateConfigurationFile(projectData) {
        return undefined;
    }
    async cleanProject(projectRoot, projectData) {
        return null;
    }
    afterCreateProject(projectRoot, projectData) {
        this.$fs.rename(path.join(projectRoot, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER), path.join(projectRoot, projectData.projectName));
    }
    async buildProject(projectRoot, projectData, buildData) {
        const platformData = this.getPlatformData(projectData);
        const handler = (data) => {
            this.emit(constants.BUILD_OUTPUT_EVENT_NAME, data);
        };
        if (buildData.buildForDevice) {
            await this.$iOSSigningService.setupSigningForDevice(projectRoot, projectData, buildData);
            await (0, helpers_1.attachAwaitDetach)(constants.BUILD_OUTPUT_EVENT_NAME, this.$childProcess, handler, this.$xcodebuildService.buildForDevice(platformData, projectData, buildData));
        }
        else if (buildData.buildForAppStore) {
            await (0, helpers_1.attachAwaitDetach)(constants.BUILD_OUTPUT_EVENT_NAME, this.$childProcess, handler, this.$xcodebuildService.buildForAppStore(platformData, projectData, buildData));
        }
        else {
            await (0, helpers_1.attachAwaitDetach)(constants.BUILD_OUTPUT_EVENT_NAME, this.$childProcess, handler, this.$xcodebuildService.buildForSimulator(platformData, projectData, buildData));
        }
        this.validateApplicationIdentifier(projectData);
    }
    isPlatformPrepared(projectRoot, projectData) {
        return this.$fs.exists(path.join(projectRoot, projectData.projectName, constants.APP_FOLDER_NAME));
    }
    cleanDeviceTempFolder(deviceIdentifier) {
        return Promise.resolve();
    }
    async isDynamicFramework(frameworkPath) {
        const isDynamicFrameworkBundle = async (bundlePath, frameworkName) => {
            const frameworkBinaryPath = path.join(bundlePath, frameworkName);
            const fileResult = (await this.$childProcess.spawnFromEvent("file", [frameworkBinaryPath], "close")).stdout;
            const isDynamicallyLinked = _.includes(fileResult, "dynamically linked");
            return isDynamicallyLinked;
        };
        if (path.extname(frameworkPath) === ".xcframework") {
            let isDynamic = true;
            const plistJson = this.$plistParser.parseFileSync(path.join(frameworkPath, "Info.plist"));
            for (const library of plistJson.AvailableLibraries) {
                const singlePlatformFramework = path.join(frameworkPath, library.LibraryIdentifier, library.LibraryPath);
                if (this.$fs.exists(singlePlatformFramework)) {
                    const frameworkName = path.basename(singlePlatformFramework, path.extname(singlePlatformFramework));
                    isDynamic = await isDynamicFrameworkBundle(singlePlatformFramework, frameworkName);
                    break;
                }
            }
            return isDynamic;
        }
        else {
            const frameworkName = path.basename(frameworkPath, path.extname(frameworkPath));
            return await isDynamicFrameworkBundle(frameworkPath, frameworkName);
        }
    }
    async addFramework(frameworkPath, projectData) {
        if (this.$hostInfo.isWindows) {
            return;
        }
        this.validateFramework(frameworkPath);
        const project = this.createPbxProj(projectData);
        const frameworkAddOptions = { customFramework: true };
        const dynamic = await this.isDynamicFramework(frameworkPath);
        if (dynamic) {
            frameworkAddOptions["embed"] = true;
            frameworkAddOptions["sign"] = true;
        }
        if (this.$options.hostProjectPath) {
            // always mark xcframeworks for embedding
            frameworkAddOptions["embed"] = true;
            frameworkAddOptions["sign"] = false;
        }
        // Note: we used to prepend "$(SRCROOT)/" to the framework path, but seems like it's not needed anymore
        // "$(SRCROOT)/" +
        const frameworkRelativePath = this.getLibSubpathRelativeToProjectPath(frameworkPath, projectData);
        project.addFramework(frameworkRelativePath, frameworkAddOptions);
        // filePathsArray, buildPhaseType, comment, target, optionsOrFolderType, subfolderPath
        // project.addBuildPhase(
        // 	[],
        // 	"PBXShellScriptBuildPhase",
        // 	"Debug SRCROOT",
        // 	undefined,
        // 	{
        // 		shellPath: "/bin/sh",
        // 		shellScript: `echo "SRCROOT: $SRCROOT"`,
        // 	}
        // );
        this.savePbxProj(project, projectData);
    }
    async addStaticLibrary(staticLibPath, projectData) {
        // Copy files to lib folder.
        const libraryName = path.basename(staticLibPath, ".a");
        const headersSubpath = path.join(path.dirname(staticLibPath), "include", libraryName);
        // Add static library to project file and setup header search paths
        const project = this.createPbxProj(projectData);
        const relativeStaticLibPath = this.getLibSubpathRelativeToProjectPath(staticLibPath, projectData);
        project.addFramework(relativeStaticLibPath);
        const relativeHeaderSearchPath = path.join(this.getLibSubpathRelativeToProjectPath(headersSubpath, projectData));
        project.addToHeaderSearchPaths({ relativePath: relativeHeaderSearchPath });
        this.generateModulemap(headersSubpath, libraryName);
        this.savePbxProj(project, projectData);
    }
    async prepareProject(projectData, prepareData) {
        const projectRoot = this.$options.hostProjectPath
            ? this.$options.hostProjectPath
            : path.join(projectData.platformsDir, this.$devicePlatformsConstants.iOS.toLowerCase());
        const platformData = this.getPlatformData(projectData);
        const pluginsData = this.getAllProductionPlugins(projectData);
        const pbxProjPath = this.getPbxProjPath(projectData);
        this.$iOSExtensionsService.removeExtensions({ pbxProjPath });
        await this.addExtensions(projectData, pluginsData);
        const resourcesDirectoryPath = projectData.getAppResourcesDirectoryPath();
        const provision = prepareData && prepareData.provision;
        const teamId = prepareData && prepareData.teamId;
        if (provision) {
            await this.$iOSSigningService.setupSigningFromProvision(projectRoot, projectData, provision, prepareData.mobileProvisionData);
        }
        if (teamId) {
            await this.$iOSSigningService.setupSigningFromTeam(projectRoot, projectData, teamId);
        }
        const project = this.createPbxProj(projectData);
        if (this.$options.hostProjectPath) {
            try {
                project.addPbxGroup([], "NativeScript", "NativeScript", null, {
                    isMain: true,
                    filesRelativeToProject: true,
                    uuid: "NATIVESCRIPTNATIVESCRIPT",
                });
                /**
                 * 1. Add platforms/ios/{projectname}/app build to the host app
                 */
                // Note: allow customization of this targetFolderName
                // const targetFolderName = "app";
                const buildFolderPath = path.join(this.$options.hostProjectPath, projectData.projectName);
                project.addResourceFile(buildFolderPath, {}, "NATIVESCRIPTNATIVESCRIPT");
                // filePathsArray, buildPhaseType, comment, target, optionsOrFolderType, subfolderPath
                // project.addBuildPhase(
                // 	[],
                // 	"PBXShellScriptBuildPhase",
                // 	"Copy Metadata (DEBUG)",
                // 	undefined,
                // 	{
                // 		shellPath: "/bin/sh",
                // 		shellScript: `cp ./platforms/ios/build/Debug-iphonesimulator/metadata-arm64.bin $CONFIGURATION_BUILD_DIR`,
                // 		outputPaths: [
                // 			JSON.stringify("$(CONFIGURATION_BUILD_DIR)/metadata-arm64.bin"),
                // 			// JSON.stringify("$(CONFIGURATION_BUILD_DIR)/metadata-arm64e.bin"),
                // 			// JSON.stringify("$(CONFIGURATION_BUILD_DIR)/metadata-i386.bin"),
                // 			// JSON.stringify("$(CONFIGURATION_BUILD_DIR)/metadata-x86_64.bin"),
                // 		],
                // 	}
                // );
                const metadataPath = path.relative(this.$options.hostProjectPath, buildFolderPath);
                project.addToOtherLinkerFlags(JSON.stringify(`-sectcreate __DATA __TNSMetadata "${metadataPath}/metadata-arm64.bin"`));
                // // no shorthand way to get UUID of build phase that i can tell
                // // methods return the phase as an object but ommitted the actual key (uuid we need)
                // // this does it same way nativescript-dev-xcode does but gets the uuid we need
                // const resourcesBuildPhaseKeys = Object.keys(
                // 	project.hash.project.objects["PBXResourcesBuildPhase"]
                // );
                // // console.log('resourcesBuildPhaseKeys:', resourcesBuildPhaseKeys);
                // const buildPhaseUUID = resourcesBuildPhaseKeys[0];
                // const comment = `${targetFolderName} in Resources`;
                // project.hash.project.objects["PBXResourcesBuildPhase"][
                // 	buildPhaseUUID
                // ].files.forEach((f: any) => {
                // 	console.log(f);
                // });
                // if (
                // 	!project.hash.project.objects["PBXResourcesBuildPhase"][
                // 		buildPhaseUUID
                // 	].files.find((f: any) => f.comment === comment)
                // ) {
                // 	project.addResourceFile(buildFolderPath, {}, buildPhaseUUID);
                // }
                /**
                 * 2. Ensure metadata is copied as a file
                 * 		The apps metadata-{arch}.bin should be added as a file reference.
                 */
                // TODO
                this.savePbxProj(project, projectData);
            }
            catch (err) {
                this.$logger.trace("Error adding NativeScript group to host project", err);
            }
        }
        const resources = project.pbxGroupByName("Resources");
        if (resources && !this.$options.hostProjectPath) {
            const references = project.pbxFileReferenceSection();
            const xcodeProjectImages = _.map(resources.children, (resource) => this.replace(references[resource.value].name));
            this.$logger.trace("Images from Xcode project");
            this.$logger.trace(xcodeProjectImages);
            const appResourcesImages = this.$fs.readDirectory(this.getAppResourcesDestinationDirectoryPath(projectData));
            this.$logger.trace("Current images from App_Resources");
            this.$logger.trace(appResourcesImages);
            const imagesToAdd = _.difference(appResourcesImages, xcodeProjectImages);
            this.$logger.trace(`New images to add into xcode project: ${imagesToAdd.join(", ")}`);
            _.each(imagesToAdd, (image) => project.addResourceFile(path.relative(this.getPlatformData(projectData).projectRoot, path.join(this.getAppResourcesDestinationDirectoryPath(projectData), image))));
            const imagesToRemove = _.difference(xcodeProjectImages, appResourcesImages);
            this.$logger.trace(`Images to remove from xcode project: ${imagesToRemove.join(", ")}`);
            _.each(imagesToRemove, (image) => project.removeResourceFile(path.join(this.getAppResourcesDestinationDirectoryPath(projectData), image)));
            this.savePbxProj(project, projectData);
            let resourcesNativeCodePath = path.join(resourcesDirectoryPath, platformData.normalizedPlatformName, constants.NATIVE_SOURCE_FOLDER);
            if (!this.$fs.exists(resourcesNativeCodePath)) {
                resourcesNativeCodePath = path.join(resourcesDirectoryPath, this.$devicePlatformsConstants.iOS, constants.NATIVE_SOURCE_FOLDER);
            }
            await this.prepareNativeSourceCode(constants.TNS_NATIVE_SOURCE_GROUP_NAME, resourcesNativeCodePath, projectData);
            const nativeSource = this.$projectConfigService.getValue(`${this._platformData.platformNameLowerCase}.NativeSource`, []);
            if (nativeSource === null || nativeSource === void 0 ? void 0 : nativeSource.length) {
                for (const source of nativeSource) {
                    await this.prepareNativeSourceCode(source.name, source.path, projectData);
                }
            }
        }
        this.$iOSWatchAppService.removeWatchApp({ pbxProjPath });
        const addedWatchApp = await this.$iOSWatchAppService.addWatchAppFromPath({
            watchAppFolderPath: path.join(resourcesDirectoryPath, platformData.normalizedPlatformName),
            projectData,
            platformData,
            pbxProjPath,
        });
        if (addedWatchApp) {
            this.$logger.warn("The support for Apple Watch App is currently in Beta. For more information about the current development state and any known issues, please check the relevant GitHub issue: https://github.com/NativeScript/nativescript-cli/issues/4589");
        }
    }
    prepareAppResources(projectData) {
        const platformData = this.getPlatformData(projectData);
        const projectAppResourcesPath = projectData.getAppResourcesDirectoryPath(projectData.projectDir);
        const platformsAppResourcesPath = this.getAppResourcesDestinationDirectoryPath(projectData);
        this.$fs.deleteDirectory(platformsAppResourcesPath);
        this.$fs.ensureDirectoryExists(platformsAppResourcesPath);
        const platformAppResourcesPath = path.join(projectAppResourcesPath, platformData.normalizedPlatformName);
        // this allows App_Resources/visionOS
        if (this.$fs.exists(platformAppResourcesPath)) {
            this.$fs.copyFile(path.join(platformAppResourcesPath, "*"), platformsAppResourcesPath);
        }
        else {
            // otherwise falls back to App_Resources/iOS
            this.$fs.copyFile(path.join(projectAppResourcesPath, this.$devicePlatformsConstants.iOS, "*"), platformsAppResourcesPath);
        }
        this.$fs.deleteFile(path.join(platformsAppResourcesPath, platformData.configurationFileName));
        this.$fs.deleteFile(path.join(platformsAppResourcesPath, constants.PODFILE_NAME));
        this.$fs.deleteDirectory(path.join(platformsAppResourcesPath, constants.NATIVE_SOURCE_FOLDER));
        this.$fs.deleteDirectory(path.join(platformsAppResourcesPath, constants.NATIVE_EXTENSION_FOLDER));
        this.$fs.deleteDirectory(path.join(platformsAppResourcesPath, "watchapp"));
        this.$fs.deleteDirectory(path.join(platformsAppResourcesPath, "watchextension"));
    }
    async processConfigurationFilesFromAppResources(projectData, opts) {
        await this.mergeInfoPlists(projectData, opts);
        await this.$iOSEntitlementsService.merge(projectData);
        await this.mergeProjectXcconfigFiles(projectData);
    }
    ensureConfigurationFileInAppResources() {
        return null;
    }
    async mergeInfoPlists(projectData, buildOptions) {
        const projectDir = projectData.projectDir;
        const infoPlistPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName);
        this.ensureConfigurationFileInAppResources();
        const reporterTraceMessage = "Info.plist:";
        const reporter = {
            log: (txt) => this.$logger.trace(`${reporterTraceMessage} ${txt}`),
            warn: (txt) => this.$logger.warn(`${reporterTraceMessage} ${txt}`),
        };
        const session = new plist_merge_patch_1.PlistSession(reporter);
        const makePatch = (plistPath) => {
            if (!this.$fs.exists(plistPath)) {
                this.$logger.trace("No plist found at: " + plistPath);
                return;
            }
            this.$logger.trace("Schedule merge plist at: " + plistPath);
            session.patch({
                name: path.relative(projectDir, plistPath),
                read: () => this.$fs.readText(plistPath),
            });
        };
        const allPlugins = this.getAllProductionPlugins(projectData);
        for (const plugin of allPlugins) {
            const pluginInfoPlistPath = path.join(plugin.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME), this.getPlatformData(projectData).configurationFileName);
            makePatch(pluginInfoPlistPath);
        }
        makePatch(infoPlistPath);
        if (projectData.projectIdentifiers && projectData.projectIdentifiers.ios) {
            session.patch({
                name: "CFBundleIdentifier from package.json nativescript.id",
                read: () => `<?xml version="1.0" encoding="UTF-8"?>
						<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
						<plist version="1.0">
						<dict>
							<key>CFBundleIdentifier</key>
							<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
						</dict>
						</plist>`,
            });
        }
        if (!buildOptions.release &&
            projectData.projectIdentifiers &&
            projectData.projectIdentifiers.ios) {
            session.patch({
                name: "CFBundleURLTypes from package.json nativescript.id",
                read: () => `<?xml version="1.0" encoding="UTF-8"?>
						<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
						<plist version="1.0">
						<dict>
							<key>CFBundleURLTypes</key>
							<array>
								<dict>
									<key>CFBundleTypeRole</key>
									<string>Editor</string>
									<key>CFBundleURLSchemes</key>
									<array>
										<string>${projectData.projectIdentifiers.ios.replace(/[^A-Za-z0-9]/g, "")}</string>
									</array>
								</dict>
							</array>
						</dict>
						</plist>`,
            });
        }
        const plistContent = session.build();
        this.$logger.trace("Info.plist: Write to: " +
            this.getPlatformData(projectData).configurationFilePath);
        this.$fs.writeFile(this.getPlatformData(projectData).configurationFilePath, plistContent);
    }
    getAllProductionPlugins(projectData) {
        return (this.$injector.resolve("pluginsService")).getAllProductionPlugins(projectData, this.getPlatformData(projectData).platformNameLowerCase);
    }
    replace(name) {
        if (_.startsWith(name, '"')) {
            name = name.substr(1, name.length - 2);
        }
        return name.replace(/\\\"/g, '"');
    }
    getLibSubpathRelativeToProjectPath(targetPath, projectData) {
        const projectRoot = this.getPlatformData(projectData).projectRoot;
        const frameworkPath = path.relative(projectRoot, targetPath);
        // console.log({
        // 	targetPath,
        // 	projectRoot,
        // 	frameworkPath,
        // 	resolved: path.resolve(projectRoot, frameworkPath),
        // });
        return frameworkPath;
    }
    getPbxProjPath(projectData) {
        if (this.$options.hostProjectPath) {
            let xcodeProjectPath = this.$xcprojService.findXcodeProject(this.$options.hostProjectPath);
            if (!xcodeProjectPath) {
                this.$errors.fail("Xcode project not found at the specified directory");
            }
            return path.join(xcodeProjectPath, "project.pbxproj");
        }
        return path.join(this.$xcprojService.getXcodeprojPath(projectData, this.getPlatformData(projectData).projectRoot), "project.pbxproj");
    }
    createPbxProj(projectData) {
        const project = new this.$xcode.project(this.getPbxProjPath(projectData));
        project.parseSync();
        return project;
    }
    savePbxProj(project, projectData, omitEmptyValues) {
        return this.$fs.writeFile(this.getPbxProjPath(projectData), project.writeSync({ omitEmptyValues }));
    }
    async preparePluginNativeCode(pluginData, projectData, opts) {
        const pluginPlatformsFolderPath = pluginData.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME);
        const sourcePath = path.join(pluginPlatformsFolderPath, "src");
        await this.prepareNativeSourceCode(pluginData.name, sourcePath, projectData);
        await this.prepareResources(pluginPlatformsFolderPath, pluginData, projectData);
        await this.prepareFrameworks(pluginPlatformsFolderPath, pluginData, projectData);
        await this.prepareStaticLibs(pluginPlatformsFolderPath, pluginData, projectData);
    }
    async removePluginNativeCode(pluginData, projectData) {
        const pluginPlatformsFolderPath = pluginData.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME);
        this.removeNativeSourceCode(pluginPlatformsFolderPath, pluginData, projectData);
        this.removeFrameworks(pluginPlatformsFolderPath, pluginData, projectData);
        this.removeStaticLibs(pluginPlatformsFolderPath, pluginData, projectData);
        const projectRoot = this.getPlatformData(projectData).projectRoot;
        this.$cocoapodsService.removePodfileFromProject(pluginData.name, this.$cocoapodsService.getPluginPodfilePath(pluginData), projectData, projectRoot);
    }
    async handleNativeDependenciesChange(projectData, opts) {
        const platformData = this.getPlatformData(projectData);
        const pluginsData = this.getAllProductionPlugins(projectData);
        this.setProductBundleIdentifier(projectData);
        await this.applyPluginsCocoaPods(pluginsData, projectData, platformData);
        await this.$cocoapodsService.applyPodfileFromAppResources(projectData, platformData);
        await this.$cocoapodsService.applyPodfileArchExclusions(projectData, platformData);
        await this.$cocoapodsService.applyPodfileFromExtensions(projectData, platformData);
        const projectPodfilePath = this.$cocoapodsService.getProjectPodfilePath(platformData.projectRoot);
        if (this.$fs.exists(projectPodfilePath)) {
            await this.$cocoapodsService.executePodInstall(platformData.projectRoot, this.$xcprojService.getXcodeprojPath(projectData, platformData.projectRoot));
            // The `pod install` command adds a new target to the .pbxproject. This target adds additional build phases to Xcode project.
            // Some of these phases relies on env variables (like PODS_PODFILE_DIR_PATH or PODS_ROOT).
            // These variables are produced from merge of pod's xcconfig file and project's xcconfig file.
            // So the correct order is `pod install` to be executed before merging pod's xcconfig file.
            await this.$cocoapodsService.mergePodXcconfigFile(projectData, platformData, opts);
        }
        const pluginSpmPackages = [];
        for (const plugin of pluginsData) {
            if (plugin.fullPath) {
                const pluginConfigPath = path.join(plugin.fullPath, constants.CONFIG_FILE_NAME_TS);
                if (this.$fs.exists(pluginConfigPath)) {
                    const config = this.$projectConfigService.readConfig(plugin.fullPath);
                    const packages = _.get(config, `${platformData.platformNameLowerCase}.SPMPackages`, []);
                    if (packages.length) {
                        pluginSpmPackages.push(...packages);
                    }
                }
            }
        }
        await this.$spmService.applySPMPackages(platformData, projectData, pluginSpmPackages);
    }
    beforePrepareAllPlugins(projectData, dependencies) {
        return Promise.resolve(dependencies);
    }
    async checkForChanges(changesInfo, prepareData, projectData) {
        const { provision, teamId } = prepareData;
        const hasProvision = provision !== undefined;
        const hasTeamId = teamId !== undefined;
        if (hasProvision || hasTeamId) {
            // Check if the native project's signing is set to the provided provision...
            const pbxprojPath = this.getPbxProjPath(projectData);
            if (this.$fs.exists(pbxprojPath)) {
                const xcode = this.$pbxprojDomXcode.Xcode.open(pbxprojPath);
                const signing = xcode.getSigning(projectData.projectName);
                if (hasProvision) {
                    if (signing && signing.style === "Manual") {
                        for (const name in signing.configurations) {
                            const config = signing.configurations[name];
                            if (config.uuid !== provision && config.name !== provision) {
                                changesInfo.signingChanged = true;
                                break;
                            }
                        }
                    }
                    else {
                        // Specifying provisioning profile requires "Manual" signing style.
                        // If the current signing style was not "Manual" it was probably "Automatic" or,
                        // it was not uniform for the debug and release build configurations.
                        changesInfo.signingChanged = true;
                    }
                }
                if (hasTeamId) {
                    if (signing && signing.style === "Automatic") {
                        if (signing.team !== teamId) {
                            const teamIdsForName = await this.$iOSProvisionService.getTeamIdsWithName(teamId);
                            if (!teamIdsForName.some((id) => id === signing.team)) {
                                changesInfo.signingChanged = true;
                            }
                        }
                    }
                    else {
                        // Specifying team id or name requires "Automatic" signing style.
                        // If the current signing style was not "Automatic" it was probably "Manual".
                        changesInfo.signingChanged = true;
                    }
                }
            }
            else {
                changesInfo.signingChanged = true;
            }
        }
    }
    getDeploymentTarget(projectData) {
        const target = this.$xcconfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "IPHONEOS_DEPLOYMENT_TARGET");
        return target;
    }
    setProductBundleIdentifier(projectData) {
        const project = this.createPbxProj(projectData);
        this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties([
            {
                name: "PRODUCT_BUNDLE_IDENTIFIER",
                value: `"${projectData.projectIdentifiers.ios}"`,
            },
        ], projectData.projectName, project);
        this.savePbxProj(project, projectData);
    }
    getAllLibsForPluginWithFileExtension(pluginData, fileExtension) {
        const fileExtensions = _.isArray(fileExtension)
            ? fileExtension
            : [fileExtension];
        const filterCallback = (fileName, pluginPlatformsFolderPath) => fileExtensions.indexOf(path.extname(fileName)) !== -1;
        return this.getAllNativeLibrariesForPlugin(pluginData, IOSProjectService.IOS_PLATFORM_NAME, filterCallback);
    }
    validateFramework(libraryPath) {
        const infoPlistPath = path.join(libraryPath, constants.INFO_PLIST_FILE_NAME);
        if (!this.$fs.exists(infoPlistPath)) {
            this.$errors.fail("The bundle at %s does not contain an Info.plist file.", libraryPath);
        }
        const plistJson = this.$plistParser.parseFileSync(infoPlistPath);
        const packageType = plistJson["CFBundlePackageType"];
        if (packageType !== "FMWK" && packageType !== "XFWK") {
            this.$errors.fail("The bundle at %s does not appear to be a dynamic framework.", libraryPath);
        }
    }
    replaceFileContent(file, projectData) {
        const fileContent = this.$fs.readText(file);
        const replacedContent = helpers.stringReplaceAll(fileContent, IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER, projectData.projectName);
        this.$fs.writeFile(file, replacedContent);
    }
    replaceFileName(fileNamePart, fileRootLocation, projectData) {
        const oldFileName = IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER + fileNamePart;
        const newFileName = projectData.projectName + fileNamePart;
        this.$fs.rename(path.join(fileRootLocation, oldFileName), path.join(fileRootLocation, newFileName));
    }
    async prepareNativeSourceCode(groupName, sourceFolderPath, projectData) {
        const project = this.createPbxProj(projectData);
        const group = await this.getRootGroup(groupName, sourceFolderPath);
        project.addPbxGroup(group.files, group.name, group.path, null, {
            isMain: true,
            filesRelativeToProject: true,
        });
        project.addToHeaderSearchPaths(group.path);
        const headerFiles = this.$fs.exists(sourceFolderPath)
            ? this.$fs.enumerateFilesInDirectorySync(sourceFolderPath, (file, stat) => stat.isDirectory() || path.extname(file) === ".h")
            : [];
        if (headerFiles.length > 0 &&
            !this.$fs.exists(path.join(sourceFolderPath, "module.modulemap"))) {
            this.$logger.warn(`warning: Directory ${sourceFolderPath} with native iOS source code doesn't contain a modulemap file. Metadata for it will not be generated and it will not be accessible from JavaScript. To learn more see https://docs.nativescript.org/guides/ios-source-code`);
        }
        this.savePbxProj(project, projectData);
    }
    async addExtensions(projectData, pluginsData) {
        const resorcesExtensionsPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, constants.NATIVE_EXTENSION_FOLDER);
        const platformData = this.getPlatformData(projectData);
        const pbxProjPath = this.getPbxProjPath(projectData);
        const addedExtensionsFromResources = await this.$iOSExtensionsService.addExtensionsFromPath({
            extensionsFolderPath: resorcesExtensionsPath,
            projectData,
            platformData,
            pbxProjPath,
        });
        let addedExtensionsFromPlugins = false;
        for (const pluginIndex in pluginsData) {
            const pluginData = pluginsData[pluginIndex];
            const pluginPlatformsFolderPath = pluginData.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME);
            const extensionPath = path.join(pluginPlatformsFolderPath, constants.NATIVE_EXTENSION_FOLDER);
            const addedExtensionFromPlugin = await this.$iOSExtensionsService.addExtensionsFromPath({
                extensionsFolderPath: extensionPath,
                projectData,
                platformData,
                pbxProjPath,
            });
            addedExtensionsFromPlugins =
                addedExtensionsFromPlugins || addedExtensionFromPlugin;
        }
        if (addedExtensionsFromResources || addedExtensionsFromPlugins) {
            this.$logger.warn("Let us know if there are other Extension features you'd like! https://github.com/NativeScript/NativeScript/issues");
        }
    }
    async getRootGroup(name, rootPath) {
        const filePathsArr = [];
        const rootGroup = {
            name: name,
            files: filePathsArr,
            path: rootPath,
        };
        if (fastGlob.isDynamicPattern(rootPath)) {
            const projectRoot = this.$projectDataService.getProjectData().projectDir;
            const filePaths = await fastGlob(rootPath);
            for (const filePath of filePaths) {
                const sourceFilePath = path.normalize(path.join(projectRoot, filePath));
                filePathsArr.push(sourceFilePath);
            }
        }
        else {
            if (this.$fs.exists(rootPath)) {
                const stats = this.$fs.getFsStats(rootPath);
                if (stats.isDirectory() && !this.$fs.isEmptyDir(rootPath)) {
                    this.$fs.readDirectory(rootPath).forEach((fileName) => {
                        const filePath = path.join(rootGroup.path, fileName);
                        filePathsArr.push(filePath);
                    });
                }
            }
        }
        return rootGroup;
    }
    async prepareResources(pluginPlatformsFolderPath, pluginData, projectData) {
        const project = this.createPbxProj(projectData);
        const resourcesPath = path.join(pluginPlatformsFolderPath, "Resources");
        if (this.$fs.exists(resourcesPath) && !this.$fs.isEmptyDir(resourcesPath)) {
            for (const fileName of this.$fs.readDirectory(resourcesPath)) {
                const filePath = path.join(resourcesPath, fileName);
                project.addResourceFile(filePath);
            }
        }
        this.savePbxProj(project, projectData);
    }
    async prepareFrameworks(pluginPlatformsFolderPath, pluginData, projectData) {
        for (const fileName of this.getAllLibsForPluginWithFileExtension(pluginData, FRAMEWORK_EXTENSIONS)) {
            await this.addFramework(path.join(pluginPlatformsFolderPath, fileName), projectData);
        }
    }
    async prepareStaticLibs(pluginPlatformsFolderPath, pluginData, projectData) {
        for (const fileName of this.getAllLibsForPluginWithFileExtension(pluginData, ".a")) {
            await this.addStaticLibrary(path.join(pluginPlatformsFolderPath, fileName), projectData);
        }
    }
    async removeNativeSourceCode(pluginPlatformsFolderPath, pluginData, projectData) {
        const project = this.createPbxProj(projectData);
        const group = await this.getRootGroup(pluginData.name, pluginPlatformsFolderPath);
        project.removePbxGroup(group.name, group.path);
        project.removeFromHeaderSearchPaths(group.path);
        this.savePbxProj(project, projectData);
    }
    removeFrameworks(pluginPlatformsFolderPath, pluginData, projectData) {
        const project = this.createPbxProj(projectData);
        _.each(this.getAllLibsForPluginWithFileExtension(pluginData, FRAMEWORK_EXTENSIONS), (fileName) => {
            const relativeFrameworkPath = this.getLibSubpathRelativeToProjectPath(fileName, projectData);
            project.removeFramework(relativeFrameworkPath, {
                customFramework: true,
                embed: true,
            });
        });
        this.savePbxProj(project, projectData);
    }
    removeStaticLibs(pluginPlatformsFolderPath, pluginData, projectData) {
        const project = this.createPbxProj(projectData);
        _.each(this.getAllLibsForPluginWithFileExtension(pluginData, ".a"), (fileName) => {
            const staticLibPath = path.join(pluginPlatformsFolderPath, fileName);
            const relativeStaticLibPath = this.getLibSubpathRelativeToProjectPath(path.basename(staticLibPath), projectData);
            project.removeFramework(relativeStaticLibPath);
            const headersSubpath = path.join("include", path.basename(staticLibPath, ".a"));
            const relativeHeaderSearchPath = path.join(this.getLibSubpathRelativeToProjectPath(headersSubpath, projectData));
            project.removeFromHeaderSearchPaths({
                relativePath: relativeHeaderSearchPath,
            });
        });
        this.savePbxProj(project, projectData);
    }
    generateModulemap(headersFolderPath, libraryName) {
        const headersFilter = (fileName, containingFolderPath) => path.extname(fileName) === ".h" &&
            this.$fs.getFsStats(path.join(containingFolderPath, fileName)).isFile();
        const headersFolderContents = this.$fs.readDirectory(headersFolderPath);
        let headers = _(headersFolderContents)
            .filter((item) => headersFilter(item, headersFolderPath))
            .value();
        if (!headers.length) {
            this.$fs.deleteFile(path.join(headersFolderPath, "module.modulemap"));
            return;
        }
        headers = _.map(headers, (value) => `header "${value}"`);
        const modulemap = `module ${libraryName} { explicit module ${libraryName} { ${headers.join(" ")} } }`;
        this.$fs.writeFile(path.join(headersFolderPath, "module.modulemap"), modulemap);
    }
    async mergeProjectXcconfigFiles(projectData) {
        const platformData = this.getPlatformData(projectData);
        const pluginsXcconfigFilePaths = _.values(this.$xcconfigService.getPluginsXcconfigFilePaths(platformData.projectRoot));
        for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
            this.$fs.deleteFile(pluginsXcconfigFilePath);
        }
        const allPlugins = this.getAllProductionPlugins(projectData);
        for (const plugin of allPlugins) {
            const pluginPlatformsFolderPath = plugin.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME);
            const pluginXcconfigFilePath = path.join(pluginPlatformsFolderPath, constants_2.BUILD_XCCONFIG_FILE_NAME);
            if (this.$fs.exists(pluginXcconfigFilePath)) {
                for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
                    await this.$xcconfigService.mergeFiles(pluginXcconfigFilePath, pluginsXcconfigFilePath);
                }
            }
        }
        const appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, constants_2.BUILD_XCCONFIG_FILE_NAME);
        if (this.$fs.exists(appResourcesXcconfigPath)) {
            for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
                await this.$xcconfigService.mergeFiles(appResourcesXcconfigPath, pluginsXcconfigFilePath);
            }
        }
        for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
            if (!this.$fs.exists(pluginsXcconfigFilePath)) {
                // We need the pluginsXcconfig file to exist in platforms dir as it is required in the native template:
                // https://github.com/NativeScript/ios-runtime/blob/9c2b7b5f70b9bee8452b7a24aa6b646214c7d2be/build/project-template/__PROJECT_NAME__/build-debug.xcconfig#L3
                // From Xcode 10 in case the file is missing, this include fails and the build itself fails (was a warning in previous Xcode versions).
                this.$fs.writeFile(pluginsXcconfigFilePath, "");
            }
        }
        for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
            // Set Entitlements Property to point to default file if not set explicitly by the user.
            const entitlementsPropertyValue = this.$xcconfigService.readPropertyValue(pluginsXcconfigFilePath, constants.CODE_SIGN_ENTITLEMENTS);
            if (entitlementsPropertyValue === null &&
                this.$fs.exists(this.$iOSEntitlementsService.getPlatformsEntitlementsPath(projectData))) {
                const tempEntitlementsDir = await this.$tempService.mkdirSync("entitlements");
                const tempEntitlementsFilePath = path.join(tempEntitlementsDir, "set-entitlements.xcconfig");
                const entitlementsRelativePath = this.$iOSEntitlementsService.getPlatformsEntitlementsRelativePath(projectData);
                this.$fs.writeFile(tempEntitlementsFilePath, `CODE_SIGN_ENTITLEMENTS = ${entitlementsRelativePath}${os_1.EOL}`);
                await this.$xcconfigService.mergeFiles(tempEntitlementsFilePath, pluginsXcconfigFilePath);
            }
        }
    }
    getBuildXCConfigFilePath(projectData) {
        const buildXCConfig = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, constants_2.BUILD_XCCONFIG_FILE_NAME);
        return buildXCConfig;
    }
    validateApplicationIdentifier(projectData) {
        const infoPlistPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName);
        const mergedPlistPath = this.getPlatformData(projectData).configurationFilePath;
        if (!this.$fs.exists(infoPlistPath) || !this.$fs.exists(mergedPlistPath)) {
            return;
        }
        const infoPlist = plist.parse(this.$fs.readText(infoPlistPath));
        const mergedPlist = plist.parse(this.$fs.readText(mergedPlistPath));
        if (infoPlist.CFBundleIdentifier &&
            infoPlist.CFBundleIdentifier !== mergedPlist.CFBundleIdentifier) {
            this.$logger.warn(`[WARNING]: The CFBundleIdentifier key inside the 'Info.plist' will be overriden by the 'id' set inside the "${constants_2.CONFIG_FILE_NAME_DISPLAY}".`);
        }
    }
    async applyPluginsCocoaPods(pluginsData, projectData, platformData) {
        for (const pluginIndex in pluginsData) {
            const pluginData = pluginsData[pluginIndex];
            if (this.$fs.exists(pluginData.pluginPlatformsFolderPath(platformData.normalizedPlatformName))) {
                await this.$cocoapodsService.applyPodfileToProject(pluginData.name, this.$cocoapodsService.getPluginPodfilePath(pluginData), projectData, platformData);
            }
        }
    }
}
exports.IOSProjectService = IOSProjectService;
IOSProjectService.IOS_PROJECT_NAME_PLACEHOLDER = "__PROJECT_NAME__";
IOSProjectService.IOS_PLATFORM_NAME = "ios";
__decorate([
    (0, helpers_2.hook)("buildIOS")
], IOSProjectService.prototype, "buildProject", null);
yok_1.injector.register("iOSProjectService", IOSProjectService);
//# sourceMappingURL=ios-project-service.js.map