"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