GT2/GT2-iOS/node_modules/xdl/build/detach/IosNSBundle.js

548 lines
21 KiB
JavaScript
Raw Normal View History

2018-02-12 17:26:06 +00:00
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.configureAsync = undefined;
let _cleanPropertyListBackupsAsync = (() => {
var _ref = _asyncToGenerator(function* (context, backupPath) {
yield (_IosPlist || _load_IosPlist()).cleanBackupAsync(backupPath, 'EXShell', false);
yield (_IosPlist || _load_IosPlist()).cleanBackupAsync(backupPath, 'Info', false);
// TODO: support this in user contexts as well
if (context.type === 'service') {
const { projectName } = (_IosWorkspace || _load_IosWorkspace()).getPaths(context);
yield (_IosPlist || _load_IosPlist()).cleanBackupAsync(backupPath, `${projectName}.entitlements`, false);
}
});
return function _cleanPropertyListBackupsAsync(_x, _x2) {
return _ref.apply(this, arguments);
};
})();
/**
* Write the manifest and JS bundle to the NSBundle.
*/
let _preloadManifestAndBundleAsync = (() => {
var _ref2 = _asyncToGenerator(function* (manifest, supportingDirectory, manifestFilename, bundleFilename) {
const bundleUrl = manifest.bundleUrl;
yield (_fsExtra || _load_fsExtra()).default.writeFile(_path.default.join(supportingDirectory, manifestFilename), JSON.stringify(manifest));
yield (0, (_ExponentTools || _load_ExponentTools()).saveUrlToPathAsync)(bundleUrl, _path.default.join(supportingDirectory, bundleFilename));
return;
});
return function _preloadManifestAndBundleAsync(_x3, _x4, _x5, _x6) {
return _ref2.apply(this, arguments);
};
})();
let _preloadKernelManifestAndBundleAsync = (() => {
var _ref3 = _asyncToGenerator(function* (supportingDirectory, manifestFilename, bundleFilename) {
const { version } = yield (_Versions || _load_Versions()).newestSdkVersionAsync();
const kernelManifest = yield (0, (_ExponentTools || _load_ExponentTools()).getManifestAsync)(KERNEL_URL, {
'Exponent-SDK-Version': version,
'Exponent-Platform': 'ios'
});
return _preloadManifestAndBundleAsync(kernelManifest, supportingDirectory, manifestFilename, bundleFilename);
});
return function _preloadKernelManifestAndBundleAsync(_x7, _x8, _x9) {
return _ref3.apply(this, arguments);
};
})();
/**
* Configure a standalone entitlements file.
*/
let _configureEntitlementsAsync = (() => {
var _ref4 = _asyncToGenerator(function* (context) {
if (context.type === 'user') {
// don't modify .entitlements, print info/instructions
const exp = context.data.exp;
console.log('Your iOS ExpoKit project will not contain an .entitlements file by default. If you need specific Apple entitlements, enable them manually via Xcode or the Apple Developer website.');
let keysToFlag = [];
if (exp.ios && exp.ios.usesIcloudStorage) {
keysToFlag.push('ios.usesIcloudStorage');
}
if (exp.ios && exp.ios.associatedDomains) {
keysToFlag.push('ios.associatedDomains');
}
if (keysToFlag.length) {
console.log('We noticed the following keys in your project which may require entitlements:');
keysToFlag.forEach(function (key) {
console.log(` ${key}`);
});
}
return {};
} else {
// modify the .entitlements file
const { projectName, supportingDirectory } = (_IosWorkspace || _load_IosWorkspace()).getPaths(context);
const manifest = context.data.manifest;
const entitlementsFilename = `${projectName}.entitlements`;
const appleTeamId = context.build.ios.appleTeamId;
if (!(_fsExtra || _load_fsExtra()).default.existsSync(_path.default.join(supportingDirectory, entitlementsFilename))) {
yield (_IosPlist || _load_IosPlist()).createBlankAsync(supportingDirectory, entitlementsFilename);
}
const result = (_IosPlist || _load_IosPlist()).modifyAsync(supportingDirectory, entitlementsFilename, function (entitlements) {
// push notif entitlement changes based on build configuration
entitlements['aps-environment'] = context.build.configuration === 'Release' ? 'production' : 'development';
// remove iCloud-specific entitlements if the developer isn't using iCloud Storage with DocumentPicker
let iCloudKeys = ['com.apple.developer.icloud-container-identifiers', 'com.apple.developer.icloud-services', 'com.apple.developer.ubiquity-container-identifiers', 'com.apple.developer.ubiquity-kvstore-identifier'];
if (manifest.ios && manifest.ios.usesIcloudStorage && appleTeamId) {
iCloudKeys.forEach(function (key) {
if (entitlements.hasOwnProperty(key)) {
switch (key) {
case 'com.apple.developer.icloud-container-identifiers':
entitlements[key] = ['iCloud.' + manifest.ios.bundleIdentifier];
break;
case 'com.apple.developer.ubiquity-container-identifiers':
entitlements[key] = ['iCloud.' + manifest.ios.bundleIdentifier];
break;
case 'com.apple.developer.ubiquity-kvstore-identifier':
entitlements[key] = appleTeamId + '.' + manifest.ios.bundleIdentifier;
break;
case 'com.apple.developer.icloud-services':
entitlements[key] = ['CloudDocuments'];
break;
default:
break;
}
}
});
} else {
iCloudKeys.forEach(function (key) {
if (entitlements.hasOwnProperty(key)) {
delete entitlements[key];
}
});
}
// Add app associated domains remove exp-specific ones.
if (manifest.ios && manifest.ios.associatedDomains) {
entitlements['com.apple.developer.associated-domains'] = manifest.ios.associatedDomains;
} else if (entitlements.hasOwnProperty('com.apple.developer.associated-domains')) {
delete entitlements['com.apple.developer.associated-domains'];
}
// for now, remove any merchant ID in shell apps
// (TODO: better plan for payments)
delete entitlements['com.apple.developer.in-app-payments'];
return entitlements;
});
return result;
}
});
return function _configureEntitlementsAsync(_x10) {
return _ref4.apply(this, arguments);
};
})();
/**
* Resolve the private config for a project.
* For standalone apps, this is copied into a separate context field context.data.privateConfig
* by the turtle builder. For a local project, this is available in app.json under ios.config.
*/
/**
* Configure an iOS Info.plist for a standalone app.
*/
let _configureInfoPlistAsync = (() => {
var _ref5 = _asyncToGenerator(function* (context) {
const { supportingDirectory } = (_IosWorkspace || _load_IosWorkspace()).getPaths(context);
const config = context.config;
const privateConfig = _getPrivateConfig(context);
let result = yield (_IosPlist || _load_IosPlist()).modifyAsync(supportingDirectory, 'Info', function (infoPlist) {
// make sure this happens first:
// apply any custom information from ios.infoPlist prior to all other exponent config
let usageDescriptionKeysConfigured = {};
if (config.ios && config.ios.infoPlist) {
let extraConfig = config.ios.infoPlist;
for (let key in extraConfig) {
if (extraConfig.hasOwnProperty(key)) {
infoPlist[key] = extraConfig[key];
// if the user provides *UsageDescription keys, don't override them later.
if (_isAppleUsageDescriptionKey(key)) {
usageDescriptionKeysConfigured[key] = true;
}
}
}
}
// bundle id
infoPlist.CFBundleIdentifier = config.ios && config.ios.bundleIdentifier ? config.ios.bundleIdentifier : null;
if (!infoPlist.CFBundleIdentifier) {
throw new Error(`Cannot configure an iOS app with no bundle identifier.`);
}
// app name
infoPlist.CFBundleName = config.name;
infoPlist.CFBundleDisplayName = config.name;
// determine app linking schemes
let linkingSchemes = config.scheme ? [config.scheme] : [];
if (config.facebookScheme && config.facebookScheme.startsWith('fb')) {
linkingSchemes.push(config.facebookScheme);
}
if (privateConfig && privateConfig.googleSignIn && privateConfig.googleSignIn.reservedClientId) {
linkingSchemes.push(privateConfig.googleSignIn.reservedClientId);
}
// remove exp scheme, add app scheme(s)
infoPlist.CFBundleURLTypes = [{
CFBundleURLSchemes: linkingSchemes
}, {
// Add the generic oauth redirect, it's important that it has the name
// 'OAuthRedirect' so we can find it in app code.
CFBundleURLName: 'OAuthRedirect',
CFBundleURLSchemes: [infoPlist.CFBundleIdentifier]
}];
// add or remove other facebook config
if (config.facebookAppId) {
infoPlist.FacebookAppID = config.facebookAppId;
} else {
delete infoPlist['FacebookAppID'];
}
if (config.facebookDisplayName) {
infoPlist.FacebookDisplayName = config.facebookDisplayName;
} else {
delete infoPlist['FacebookDisplayName'];
}
// set ITSAppUsesNonExemptEncryption to let people skip manually
// entering it in iTunes Connect
if (privateConfig && privateConfig.hasOwnProperty('usesNonExemptEncryption') && privateConfig.usesNonExemptEncryption === false) {
infoPlist.ITSAppUsesNonExemptEncryption = false;
}
// google maps api key
if (privateConfig && privateConfig.googleMapsApiKey) {
infoPlist.GMSApiKey = privateConfig.googleMapsApiKey;
}
// use version from manifest
let version = config.version ? config.version : '0.0.0';
let buildNumber = config.ios && config.ios.buildNumber ? config.ios.buildNumber : '1';
infoPlist.CFBundleShortVersionString = version;
infoPlist.CFBundleVersion = buildNumber;
infoPlist.Fabric = {
APIKey: privateConfig && privateConfig.fabric && privateConfig.fabric.apiKey || DEFAULT_FABRIC_KEY,
Kits: [{
KitInfo: {},
KitName: 'Crashlytics'
}]
};
if (privateConfig && privateConfig.branch) {
infoPlist.branch_key = {
live: privateConfig.branch.apiKey
};
}
let permissionsAppName = config.name ? config.name : 'this app';
for (let key in infoPlist) {
if (infoPlist.hasOwnProperty(key) && _isAppleUsageDescriptionKey(key) && !usageDescriptionKeysConfigured.hasOwnProperty(key)) {
infoPlist[key] = infoPlist[key].replace('Expo experiences', permissionsAppName);
}
}
// 1 is iPhone, 2 is iPad
infoPlist.UIDeviceFamily = config.ios && config.ios.supportsTablet ? [1, 2] : [1];
// allow iPad-only
if (config.ios && config.ios.isTabletOnly) {
infoPlist.UIDeviceFamily = [2];
}
// context-specific plist changes
if (context.type === 'user') {
infoPlist = _configureInfoPlistForLocalDevelopment(infoPlist, context.data.exp);
_logDeveloperInfoForLocalDevelopment(infoPlist);
}
return infoPlist;
});
return result;
});
return function _configureInfoPlistAsync(_x11) {
return _ref5.apply(this, arguments);
};
})();
/**
* Configure EXShell.plist for a standalone app.
*/
let _configureShellPlistAsync = (() => {
var _ref6 = _asyncToGenerator(function* (context) {
const { supportingDirectory } = (_IosWorkspace || _load_IosWorkspace()).getPaths(context);
const config = context.config;
yield (_IosPlist || _load_IosPlist()).modifyAsync(supportingDirectory, 'EXShell', function (shellPlist) {
shellPlist.isShell = true;
shellPlist.manifestUrl = context.published.url;
shellPlist.releaseChannel = context.published.releaseChannel;
if (config.ios && config.ios.permissions) {
shellPlist.permissions = config.ios.permissions;
}
if (context.type == 'user') {
// disable manifest verification on detached apps until
// the developer adds the correct entitlements to their bundle id.
shellPlist.isManifestVerificationBypassed = true;
}
if (config.ios && config.ios.hasOwnProperty('isRemoteJSEnabled')) {
// enable/disable code push if the developer provided specific behavior
shellPlist.isRemoteJSEnabled = config.ios.isRemoteJSEnabled;
}
if (config.ios && config.ios.hasOwnProperty('loadJSInBackgroundExperimental')) {
shellPlist.loadJSInBackgroundExperimental = config.ios.loadJSInBackgroundExperimental;
}
if (!(0, (_ExponentTools || _load_ExponentTools()).manifestUsesSplashApi)(config, 'ios')) {
// for people still using the old loading api, hide the native splash screen.
// we can remove this code eventually.
shellPlist.isSplashScreenDisabled = true;
}
console.log('Using shell config:', shellPlist);
return shellPlist;
});
});
return function _configureShellPlistAsync(_x12) {
return _ref6.apply(this, arguments);
};
})();
let _downloadAssetsAsync = (() => {
var _ref7 = _asyncToGenerator(function* (assets, dest, oldFormat) {
if (!assets) {
return;
}
// Compat with exp 46.x.x, can remove when this version is phasing out.
if (typeof assets[0] === 'object') {
assets = assets.reduce(function (res, cur) {
return res.concat(cur.fileHashes.map(function (h) {
return 'asset_' + h + (cur.type ? '.' + cur.type : '');
}));
}, []);
}
const batches = (_lodash || _load_lodash()).default.chunk(assets, 5);
for (const batch of batches) {
yield Promise.all(batch.map((() => {
var _ref8 = _asyncToGenerator(function* (asset) {
const extensionIndex = asset.lastIndexOf('.');
const prefixLength = 'asset_'.length;
const hash = extensionIndex >= 0 ? asset.substring(prefixLength, extensionIndex) : asset.substring(prefixLength);
yield (0, (_ExponentTools || _load_ExponentTools()).saveUrlToPathAsync)('https://d1wp6m56sqw74a.cloudfront.net/~assets/' + hash,
// For sdk24 the runtime expects only the hash as the filename.
_path.default.join(dest, oldFormat ? hash : asset));
});
return function (_x16) {
return _ref8.apply(this, arguments);
};
})()));
}
});
return function _downloadAssetsAsync(_x13, _x14, _x15) {
return _ref7.apply(this, arguments);
};
})();
let configureAsync = (() => {
var _ref9 = _asyncToGenerator(function* (context) {
let {
intermediatesDirectory,
iosProjectDirectory,
projectName,
supportingDirectory
} = (_IosWorkspace || _load_IosWorkspace()).getPaths(context);
if (!context.published.url) {
throw new Error(`Can't configure a NSBundle without a published url.`);
}
if (context.data.manifest) {
const { supportingDirectory } = (_IosWorkspace || _load_IosWorkspace()).getPaths(context);
yield _downloadAssetsAsync(context.data.manifest.bundledAssets, supportingDirectory, context.data.manifest.sdkVersion === '24.0.0');
}
// common configuration for all contexts
console.log(`Modifying NSBundle configuration at ${supportingDirectory}...`);
yield _configureInfoPlistAsync(context);
yield _configureShellPlistAsync(context);
yield _configureEntitlementsAsync(context);
yield (_IosLaunchScreen || _load_IosLaunchScreen()).configureLaunchAssetsAsync(context, intermediatesDirectory);
if (context.type === 'user') {
const iconPath = _path.default.join(iosProjectDirectory, projectName, 'Assets.xcassets', 'AppIcon.appiconset');
yield (_IosIcons || _load_IosIcons()).createAndWriteIconsToPathAsync(context, iconPath);
} else if (context.type === 'service') {
console.log('Compiling resources...');
yield (_IosAssetArchive || _load_IosAssetArchive()).buildAssetArchiveAsync(context, supportingDirectory, intermediatesDirectory);
yield _preloadManifestAndBundleAsync(context.data.manifest, supportingDirectory, 'shell-app-manifest.json', 'shell-app.bundle');
yield _preloadKernelManifestAndBundleAsync(supportingDirectory, 'kernel-manifest.json', 'kernel.ios.bundle');
}
console.log('Cleaning up iOS...');
yield _cleanPropertyListBackupsAsync(context, supportingDirectory);
// maybe clean intermediates
if ((_fsExtra || _load_fsExtra()).default.existsSync(intermediatesDirectory)) {
(_rimraf || _load_rimraf()).default.sync(intermediatesDirectory);
}
});
return function configureAsync(_x17) {
return _ref9.apply(this, arguments);
};
})();
var _fsExtra;
function _load_fsExtra() {
return _fsExtra = _interopRequireDefault(require('fs-extra'));
}
var _path = _interopRequireDefault(require('path'));
var _rimraf;
function _load_rimraf() {
return _rimraf = _interopRequireDefault(require('rimraf'));
}
var _lodash;
function _load_lodash() {
return _lodash = _interopRequireDefault(require('lodash'));
}
var _ExponentTools;
function _load_ExponentTools() {
return _ExponentTools = require('./ExponentTools');
}
var _IosAssetArchive;
function _load_IosAssetArchive() {
return _IosAssetArchive = _interopRequireWildcard(require('./IosAssetArchive'));
}
var _IosIcons;
function _load_IosIcons() {
return _IosIcons = _interopRequireWildcard(require('./IosIcons'));
}
var _IosPlist;
function _load_IosPlist() {
return _IosPlist = _interopRequireWildcard(require('./IosPlist'));
}
var _IosLaunchScreen;
function _load_IosLaunchScreen() {
return _IosLaunchScreen = _interopRequireWildcard(require('./IosLaunchScreen'));
}
var _IosWorkspace;
function _load_IosWorkspace() {
return _IosWorkspace = _interopRequireWildcard(require('./IosWorkspace'));
}
var _StandaloneContext;
function _load_StandaloneContext() {
return _StandaloneContext = _interopRequireDefault(require('./StandaloneContext'));
}
var _Versions;
function _load_Versions() {
return _Versions = _interopRequireWildcard(require('../Versions'));
}
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
// TODO: move this somewhere else. this is duplicated in universe/exponent/template-files/keys,
// but xdl doesn't have access to that.
const DEFAULT_FABRIC_KEY = '81130e95ea13cd7ed9a4f455e96214902c721c99';
const KERNEL_URL = 'https://expo.io/@exponent/home';
function _configureInfoPlistForLocalDevelopment(config, exp) {
// add detached scheme
if (exp.isDetached && exp.detach.scheme) {
if (!config.CFBundleURLTypes) {
config.CFBundleURLTypes = [{
CFBundleURLSchemes: []
}];
}
config.CFBundleURLTypes[0].CFBundleURLSchemes.push(exp.detach.scheme);
}
// for local dev, don't specify device family here
if (config.UIDeviceFamily) {
delete config.UIDeviceFamily;
}
return config;
}
/**
* Prints warnings or info about the configured environment for local development.
*/
function _logDeveloperInfoForLocalDevelopment(infoPlist) {
// warn about *UsageDescription changes
let usageKeysConfigured = [];
for (let key in infoPlist) {
if (infoPlist.hasOwnProperty(key) && key.indexOf('UsageDescription') !== -1) {
usageKeysConfigured.push(key);
}
}
if (usageKeysConfigured.length) {
console.log('We added some permissions keys to `Info.plist` in your detached iOS project:');
usageKeysConfigured.forEach(key => {
console.log(` ${key}`);
});
console.log('You may want to revise them to include language appropriate to your project. You can also remove them if your app will never use the corresponding API. See the Apple docs for these keys.');
}
}
function _getPrivateConfig(context) {
let privateConfig;
if (context.type === 'service') {
privateConfig = context.data.privateConfig;
} else if (context.type === 'user') {
const exp = context.data.exp;
if (exp && exp.ios) {
privateConfig = exp.ios.config;
}
}
return privateConfig;
}
function _isAppleUsageDescriptionKey(key) {
return key.indexOf('UsageDescription') !== -1;
}exports.configureAsync = configureAsync;
//# sourceMappingURL=../__sourcemaps__/detach/IosNSBundle.js.map