"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.renderExpoKitPodspecAsync = renderExpoKitPodspecAsync; exports.renderPodfileAsync = renderPodfileAsync; function _fsExtra() { const data = _interopRequireDefault(require("fs-extra")); _fsExtra = function () { return data; }; return data; } function _globPromise() { const data = _interopRequireDefault(require("glob-promise")); _globPromise = function () { return data; }; return data; } function _indentString() { const data = _interopRequireDefault(require("indent-string")); _indentString = function () { return data; }; return data; } function _jsonFile() { const data = _interopRequireDefault(require("@expo/json-file")); _jsonFile = function () { return data; }; return data; } function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _ExponentTools() { const data = require("./ExponentTools"); _ExponentTools = function () { return data; }; return data; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _validatePodfileSubstitutions(substitutions) { const validKeys = [// a pod dependency on ExpoKit (can be local or remote) 'EXPOKIT_DEPENDENCY', // local path to ExpoKit dependency 'EXPOKIT_PATH', // tag to use for ExpoKit dependency 'EXPOKIT_TAG', // the contents of dependencies.json enumerated as deps in podfile format 'EXPONENT_CLIENT_DEPS', // postinstall for detached projects (defines EX_DETACHED among other things) 'PODFILE_DETACHED_POSTINSTALL', // same as previous but also defines EX_DETACHED_SERVICE 'PODFILE_DETACHED_SERVICE_POSTINSTALL', // ExponentIntegrationTests 'PODFILE_TEST_TARGET', // unversioned react native pod dependency, probably at the path given in // REACT_NATIVE_PATH, with a bunch of subspecs. 'PODFILE_UNVERSIONED_RN_DEPENDENCY', // postinstall hook for unversioned deps 'PODFILE_UNVERSIONED_POSTINSTALL', // versioned rn dependencies (paths to versioned-react-native directories) // read from template files 'PODFILE_VERSIONED_RN_DEPENDENCIES', // versioned rn postinstall hooks read from template files 'PODFILE_VERSIONED_POSTINSTALLS', // list of generated Expo subspecs to include under a versioned react native dependency 'REACT_NATIVE_EXPO_SUBSPECS', // path to use for the unversioned react native dependency 'REACT_NATIVE_PATH', // name of the main build target, e.g. Exponent 'TARGET_NAME', // path from Podfile to versioned-react-native 'VERSIONED_REACT_NATIVE_PATH', // Expo universal modules dependencies 'PODFILE_UNVERSIONED_EXPO_MODULES_DEPENDENCIES', // Universal modules configurations to be included in the Podfile 'UNIVERSAL_MODULES', // Relative path from iOS project directory to folder where unimodules are installed. 'UNIVERSAL_MODULES_PATH']; for (const key in substitutions) { if (substitutions.hasOwnProperty(key)) { if (!validKeys.includes(key)) { throw new Error(`Unrecognized Podfile template key: ${key}`); } } } return true; } function _renderExpoKitDependency(options, sdkVersion) { const sdkMajorVersion = (0, _ExponentTools().parseSdkMajorVersion)(sdkVersion); let attributes; if (options.expoKitPath) { attributes = { path: options.expoKitPath }; } else if (options.expoKitTag) { attributes = { git: 'http://github.com/expo/expo.git', tag: options.expoKitTag }; } else { attributes = { git: 'http://github.com/expo/expo.git', branch: 'master' }; } // GL subspec is available as of SDK 26 // but removed together with CPP subspec in SDK 29 if (sdkMajorVersion < 26) { attributes.subspecs = ['Core', 'CPP']; } else if (sdkMajorVersion < 29 && !process.env.EXPO_UNIVERSE_DIR) { attributes.subspecs = ['Core', 'CPP', 'GL']; } else { attributes.subspecs = ['Core']; } attributes.inhibit_warnings = true; let dependency = `pod 'ExpoKit', ${(0, _indentString().default)(_renderDependencyAttributes(attributes), 2)}`; return (0, _indentString().default)(dependency, 2); } /** * @param sdkVersion if specified, indicates which sdkVersion this project uses * as 'UNVERSIONED', e.g. if we are detaching a sdk15 project, we render * an unversioned dependency pointing at RN#sdk-15. */ function _renderUnversionedReactNativeDependency(options, sdkVersion) { let sdkMajorVersion = (0, _ExponentTools().parseSdkMajorVersion)(sdkVersion); const glogLibraryName = sdkMajorVersion < 26 ? 'GLog' : 'glog'; return (0, _indentString().default)(` ${_renderUnversionedReactDependency(options, sdkVersion)} ${_renderUnversionedYogaDependency(options)} ${_renderUnversionedThirdPartyDependency('DoubleConversion', _path().default.join('third-party-podspecs', 'DoubleConversion.podspec'), options)} ${_renderUnversionedThirdPartyDependency('Folly', _path().default.join('third-party-podspecs', 'Folly.podspec'), options)} ${_renderUnversionedThirdPartyDependency(glogLibraryName, _path().default.join('third-party-podspecs', `${glogLibraryName}.podspec`), options)} `, 2); } function _renderUnversionedReactDependency(options, sdkVersion) { if (!options.reactNativePath) { throw new Error(`Unsupported options for RN dependency: ${options}`); } let attributes = { path: options.reactNativePath, inhibit_warnings: true, subspecs: ['Core', 'ART', 'RCTActionSheet', 'RCTAnimation', 'RCTCameraRoll', 'RCTGeolocation', 'RCTImage', 'RCTNetwork', 'RCTText', 'RCTVibration', 'RCTWebSocket', 'DevSupport', 'CxxBridge'] }; return `pod 'React', ${(0, _indentString().default)(_renderDependencyAttributes(attributes), 2)}`; } function _renderUnversionedYogaDependency(options) { let attributes; if (options.reactNativePath) { attributes = { path: _path().default.join(options.reactNativePath, 'ReactCommon', 'yoga'), inhibit_warnings: true }; } else { throw new Error(`Unsupported options for Yoga dependency: ${options}`); } return `pod 'yoga', ${(0, _indentString().default)(_renderDependencyAttributes(attributes), 2)}`; } function _renderUnversionedThirdPartyDependency(podName, podspecRelativePath, options) { let attributes; if (options.reactNativePath) { attributes = { podspec: _path().default.join(options.reactNativePath, podspecRelativePath), inhibit_warnings: true }; } else { throw new Error(`Unsupported options for ${podName} dependency: ${options}`); } return `pod '${podName}', ${(0, _indentString().default)(_renderDependencyAttributes(attributes), 2)}`; } function _renderDependencyAttributes(attributes) { let attributesStrings = []; for (let key of Object.keys(attributes)) { let value = JSON.stringify(attributes[key], null, 2); attributesStrings.push(`:${key} => ${value}`); } return attributesStrings.join(',\n'); } function createSdkFilterFn(sdkVersion) { if (sdkVersion && String(sdkVersion).toUpperCase() === 'UNVERSIONED') { return () => false; } if (sdkVersion === undefined || !sdkVersion.match(/^\d+\.\d+.\d+$/)) { return; } const sdkVersionWithUnderscores = sdkVersion.replace(/\./g, '_'); return i => i.endsWith(`/ReactABI${sdkVersionWithUnderscores}.rb`); } async function _renderVersionedReactNativeDependenciesAsync(templatesDirectory, versionedReactNativePath, expoSubspecs, shellAppSdkVersion) { const filterFn = createSdkFilterFn(shellAppSdkVersion); let result = await _concatTemplateFilesInDirectoryAsync(_path().default.join(templatesDirectory, 'versioned-react-native', 'dependencies'), filterFn); expoSubspecs = expoSubspecs.map(subspec => `'${subspec}'`).join(', '); result = result.replace(/\$\{VERSIONED_REACT_NATIVE_PATH\}/g, versionedReactNativePath); result = result.replace(/\$\{REACT_NATIVE_EXPO_SUBSPECS\}/g, expoSubspecs); return result; } async function _renderVersionedReactNativePostinstallsAsync(templatesDirectory, shellAppSdkVersion) { const filterFn = createSdkFilterFn(shellAppSdkVersion); return _concatTemplateFilesInDirectoryAsync(_path().default.join(templatesDirectory, 'versioned-react-native', 'postinstalls'), filterFn); } async function _concatTemplateFilesInDirectoryAsync(directory, filterFn) { let templateFilenames = (await (0, _globPromise().default)(_path().default.join(directory, '*.rb'))).sort(); let filteredTemplateFilenames = filterFn ? templateFilenames.filter(filterFn) : templateFilenames; let templateStrings = []; // perform this in series in order to get deterministic output for (let fileIdx = 0, nFiles = filteredTemplateFilenames.length; fileIdx < nFiles; fileIdx++) { const filename = filteredTemplateFilenames[fileIdx]; let templateString = await _fsExtra().default.readFile(filename, 'utf8'); if (templateString) { templateStrings.push(templateString); } } return templateStrings.join('\n'); } function _renderDetachedPostinstall(sdkVersion, isServiceContext) { const sdkMajorVersion = (0, _ExponentTools().parseSdkMajorVersion)(sdkVersion); const podNameExpression = sdkMajorVersion < 33 ? 'target.pod_name' : 'pod_name'; const targetExpression = sdkMajorVersion < 33 ? 'target' : 'target_installation_result'; let podsRootSub = '${PODS_ROOT}'; const maybeDetachedServiceDef = isServiceContext ? `config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'EX_DETACHED_SERVICE=1'` : ''; const maybeFrameworkSearchPathDef = sdkMajorVersion < 33 ? ` # Needed for GoogleMaps 2.x config.build_settings['FRAMEWORK_SEARCH_PATHS'] ||= [] config.build_settings['FRAMEWORK_SEARCH_PATHS'] << '${podsRootSub}/GoogleMaps/Base/Frameworks' config.build_settings['FRAMEWORK_SEARCH_PATHS'] << '${podsRootSub}/GoogleMaps/Maps/Frameworks'` : ''; return ` if ${podNameExpression} == 'ExpoKit' ${targetExpression}.native_target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)'] config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'EX_DETACHED=1' ${maybeDetachedServiceDef} # Enable Google Maps support config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'HAVE_GOOGLE_MAPS=1' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'HAVE_GOOGLE_MAPS_UTILS=1' ${maybeFrameworkSearchPathDef} end end `; } function _renderUnversionedPostinstall(sdkVersion) { const podsToChangeDeployTarget = ['Amplitude-iOS', 'Analytics', 'AppAuth', 'Branch', 'CocoaLumberjack', 'FBSDKCoreKit', 'FBSDKLoginKit', 'FBSDKShareKit', 'GPUImage', 'JKBigInteger2']; const podsToChangeRB = `[${podsToChangeDeployTarget.map(pod => `'${pod}'`).join(',')}]`; const sdkMajorVersion = (0, _ExponentTools().parseSdkMajorVersion)(sdkVersion); const podNameExpression = sdkMajorVersion < 33 ? 'target.pod_name' : 'pod_name'; const targetExpression = sdkMajorVersion < 33 ? 'target' : 'target_installation_result'; // SDK31 drops support for iOS 9.0 const deploymentTarget = sdkMajorVersion > 30 ? '10.0' : '9.0'; const podsToChangeDeployTargetIfStart = sdkMajorVersion <= 33 ? ` if ${podsToChangeRB}.include? ${podNameExpression}` : ''; const podsToChangeDeployTargetIfEnd = sdkMajorVersion <= 33 ? ' end' : ''; return ` ${podsToChangeDeployTargetIfStart} ${targetExpression}.native_target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '${deploymentTarget}' end ${podsToChangeDeployTargetIfEnd} # Can't specify this in the React podspec because we need to use those podspecs for detached # projects which don't reference ExponentCPP. if ${podNameExpression}.start_with?('React') ${targetExpression}.native_target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '${deploymentTarget}' config.build_settings['HEADER_SEARCH_PATHS'] ||= ['$(inherited)'] end end # Build React Native with RCT_DEV enabled and RCT_ENABLE_INSPECTOR and # RCT_ENABLE_PACKAGER_CONNECTION disabled next unless ${podNameExpression} == 'React' ${targetExpression}.native_target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)'] config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'RCT_DEV=1' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'RCT_ENABLE_INSPECTOR=0' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'ENABLE_PACKAGER_CONNECTION=0' end `; } function _renderTestTarget(reactNativePath) { return ` target 'ExponentIntegrationTests' do inherit! :search_paths end target 'Tests' do inherit! :search_paths end `; } async function _renderPodDependenciesAsync(dependenciesConfigPath, options) { let dependencies = await new (_jsonFile().default)(dependenciesConfigPath).readAsync(); const type = options.isPodfile ? 'pod' : 'ss.dependency'; const noWarningsFlag = options.isPodfile ? `, :inhibit_warnings => true` : ''; let depsStrings = dependencies.map(dependency => { let builder = ''; if (dependency.comments) { builder += dependency.comments.map(commentLine => ` # ${commentLine}`).join('\n'); builder += '\n'; } const otherPodfileFlags = options.isPodfile && dependency.otherPodfileFlags; builder += ` ${type} '${dependency.name}', '${dependency.version}'${noWarningsFlag}${otherPodfileFlags || ''}`; return builder; }); return depsStrings.join('\n'); } async function renderExpoKitPodspecAsync(pathToTemplate, pathToOutput, moreSubstitutions) { let templatesDirectory = _path().default.dirname(pathToTemplate); let templateString = await _fsExtra().default.readFile(pathToTemplate, 'utf8'); let dependencies = await _renderPodDependenciesAsync(_path().default.join(templatesDirectory, 'dependencies.json'), { isPodfile: false }); let result = templateString.replace(/\$\{IOS_EXPOKIT_DEPS\}/g, (0, _indentString().default)(dependencies, 2)); if (moreSubstitutions && moreSubstitutions.IOS_EXPONENT_CLIENT_VERSION) { result = result.replace(/\$\{IOS_EXPONENT_CLIENT_VERSION\}/g, moreSubstitutions.IOS_EXPONENT_CLIENT_VERSION); } await _fsExtra().default.writeFile(pathToOutput, result); } function _renderUnversionedUniversalModulesDependencies(universalModules, universalModulesPath, sdkVersion) { const sdkMajorVersion = (0, _ExponentTools().parseSdkMajorVersion)(sdkVersion); if (sdkMajorVersion >= 33) { return (0, _indentString().default)(` # Install unimodules require_relative '../node_modules/react-native-unimodules/cocoapods.rb' use_unimodules!( modules_paths: ['${universalModulesPath}'], exclude: [ 'expo-bluetooth', 'expo-in-app-purchases', 'expo-payments-stripe', ], )`, 2); } else { return (0, _indentString().default)(universalModules.map(moduleInfo => _renderUnversionedUniversalModuleDependency(moduleInfo.podName, moduleInfo.path, sdkVersion)).join('\n'), 2); } } function _renderUnversionedUniversalModuleDependency(podName, path, sdkVersion) { const attributes = { path }; return `pod '${podName}', ${(0, _indentString().default)(_renderDependencyAttributes(attributes), 2)}`; } /** * @param pathToTemplate path to template Podfile * @param pathToOutput path to render final Podfile * @param moreSubstitutions dictionary of additional substitution keys and values to replace * in the template, such as: TARGET_NAME, REACT_NATIVE_PATH */ async function renderPodfileAsync(pathToTemplate, pathToOutput, moreSubstitutions, shellAppSdkVersion, sdkVersion = 'UNVERSIONED') { if (!moreSubstitutions) { moreSubstitutions = {}; } let templatesDirectory = _path().default.dirname(pathToTemplate); let templateString = await _fsExtra().default.readFile(pathToTemplate, 'utf8'); let reactNativePath = moreSubstitutions.REACT_NATIVE_PATH; let rnDependencyOptions; if (reactNativePath) { rnDependencyOptions = { reactNativePath }; } else { rnDependencyOptions = {}; } const expoKitPath = moreSubstitutions.EXPOKIT_PATH; const expoKitTag = moreSubstitutions.EXPOKIT_TAG; let expoKitDependencyOptions = {}; if (expoKitPath) { expoKitDependencyOptions = { expoKitPath }; } else if (expoKitTag) { expoKitDependencyOptions = { expoKitTag }; } let versionedRnPath = moreSubstitutions.VERSIONED_REACT_NATIVE_PATH; if (!versionedRnPath) { versionedRnPath = './versioned-react-native'; } let rnExpoSubspecs = moreSubstitutions.REACT_NATIVE_EXPO_SUBSPECS; if (!rnExpoSubspecs) { rnExpoSubspecs = ['Expo']; } let versionedDependencies = await _renderVersionedReactNativeDependenciesAsync(templatesDirectory, versionedRnPath, rnExpoSubspecs, shellAppSdkVersion); let versionedPostinstalls = await _renderVersionedReactNativePostinstallsAsync(templatesDirectory, shellAppSdkVersion); let podDependencies = await _renderPodDependenciesAsync(_path().default.join(templatesDirectory, 'dependencies.json'), { isPodfile: true }); let universalModules = moreSubstitutions.UNIVERSAL_MODULES; if (!universalModules) { universalModules = []; } let substitutions = { EXPONENT_CLIENT_DEPS: podDependencies, EXPOKIT_DEPENDENCY: _renderExpoKitDependency(expoKitDependencyOptions, sdkVersion), PODFILE_UNVERSIONED_EXPO_MODULES_DEPENDENCIES: _renderUnversionedUniversalModulesDependencies(universalModules, moreSubstitutions.UNIVERSAL_MODULES_PATH, sdkVersion), PODFILE_UNVERSIONED_RN_DEPENDENCY: _renderUnversionedReactNativeDependency(rnDependencyOptions, sdkVersion), PODFILE_UNVERSIONED_POSTINSTALL: _renderUnversionedPostinstall(sdkVersion), PODFILE_DETACHED_POSTINSTALL: _renderDetachedPostinstall(sdkVersion, false), PODFILE_DETACHED_SERVICE_POSTINSTALL: _renderDetachedPostinstall(sdkVersion, true), PODFILE_VERSIONED_RN_DEPENDENCIES: versionedDependencies, PODFILE_VERSIONED_POSTINSTALLS: versionedPostinstalls, PODFILE_TEST_TARGET: shellAppSdkVersion ? '' : _renderTestTarget(reactNativePath), ...moreSubstitutions }; _validatePodfileSubstitutions(substitutions); let result = templateString; for (let key in substitutions) { if (substitutions.hasOwnProperty(key)) { let replacement = substitutions[key]; result = result.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), replacement); } } await _fsExtra().default.writeFile(pathToOutput, result); } //# sourceMappingURL=../__sourcemaps__/detach/IosPodsTools.js.map