"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function _lodash() {
const data = _interopRequireDefault(require("lodash"));
_lodash = function () {
return data;
};
return data;
}
function _fsExtra() {
const data = _interopRequireDefault(require("fs-extra"));
_fsExtra = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function _ora() {
const data = _interopRequireDefault(require("ora"));
_ora = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _cliTable() {
const data = _interopRequireDefault(require("cli-table"));
_cliTable = function () {
return data;
};
return data;
}
function ConfigUtils() {
const data = _interopRequireWildcard(require("@expo/config"));
ConfigUtils = function () {
return data;
};
return data;
}
function _xdl() {
const data = require("@expo/xdl");
_xdl = function () {
return data;
};
return data;
}
function _CommandError() {
const data = _interopRequireDefault(require("../../CommandError"));
_CommandError = function () {
return data;
};
return data;
}
function _urlOpts() {
const data = _interopRequireDefault(require("../../urlOpts"));
_urlOpts = function () {
return data;
};
return data;
}
function appleApi() {
const data = _interopRequireWildcard(require("../build/ios/appleApi"));
appleApi = function () {
return data;
};
return data;
}
function _constants() {
const data = require("../build/constants");
_constants = function () {
return data;
};
return data;
}
function _fastlane() {
const data = require("../build/ios/appleApi/fastlane");
_fastlane = function () {
return data;
};
return data;
}
function _selectDistributionCert() {
const data = _interopRequireDefault(require("./selectDistributionCert"));
_selectDistributionCert = function () {
return data;
};
return data;
}
function _selectPushKey() {
const data = _interopRequireDefault(require("./selectPushKey"));
_selectPushKey = function () {
return data;
};
return data;
}
function _selectAdhocProvisioningProfile() {
const data = _interopRequireDefault(require("./selectAdhocProvisioningProfile"));
_selectAdhocProvisioningProfile = function () {
return data;
};
return data;
}
function _generateBundleIdentifier() {
const data = _interopRequireDefault(require("./generateBundleIdentifier"));
_generateBundleIdentifier = function () {
return data;
};
return data;
}
function _clientBuildApi() {
const data = require("./clientBuildApi");
_clientBuildApi = function () {
return data;
};
return data;
}
function _log() {
const data = _interopRequireDefault(require("../../log"));
_log = function () {
return data;
};
return data;
}
function _prompt() {
const data = _interopRequireDefault(require("../../prompt"));
_prompt = function () {
return data;
};
return data;
}
function _tagger() {
const data = require("./tagger");
_tagger = function () {
return data;
};
return data;
}
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)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const {
IOS
} = _constants().PLATFORMS;
var _default = program => {
program.command('client:ios [project-dir]').option('--apple-id <login>', 'Apple ID username (please also set the Apple ID password as EXPO_APPLE_PASSWORD environment variable).').description('Build a custom version of the Expo Client for iOS using your own Apple credentials and install it on your mobile device using Safari.').asyncActionProjectDir(async (projectDir, options) => {
const disabledServices = {
pushNotifications: {
name: 'Push Notifications',
reason: 'not yet available until API tokens are supported for the Push Notification system'
}
}; // get custom project manifest if it exists
// Note: this is the current developer's project, NOT the Expo client's manifest
const spinner = (0, _ora().default)(`Finding custom configuration for the Expo client...`).start();
const appJsonPath = options.config || _path().default.join(projectDir, 'app.json');
const appJsonExists = await ConfigUtils().fileExistsAsync(appJsonPath);
const {
exp
} = appJsonExists ? await ConfigUtils().readConfigJsonAsync(projectDir) : {};
if (exp) {
spinner.succeed(`Found custom configuration for the Expo client at ${appJsonPath}`);
} else {
spinner.warn(`Unable to find custom configuration for the Expo client`);
}
if (!_lodash().default.has(exp, 'ios.config.googleMapsApiKey')) {
const disabledReason = exp ? `ios.config.googleMapsApiKey does not exist in configuration file found in ${appJsonPath}` : 'No custom configuration file could be found. You will need to provide a json file with a valid ios.config.googleMapsApiKey field.';
disabledServices.googleMaps = {
name: 'Google Maps',
reason: disabledReason
};
}
if (_lodash().default.has(exp, 'ios.googleServicesFile')) {
const contents = await _fsExtra().default.readFile(_path().default.resolve(projectDir, exp.ios.googleServicesFile), 'base64');
exp.ios.googleServicesFile = contents;
}
const authData = await appleApi().authenticate(options);
const user = await _xdl().UserManager.getCurrentUserAsync(); // check if any builds are in flight
const {
isAllowed,
errorMessage
} = await (0, _clientBuildApi().isAllowedToBuild)({
user,
appleTeamId: authData.team.id
});
if (!isAllowed) {
throw new (_CommandError().default)('CLIENT_BUILD_REQUEST_NOT_ALLOWED', `New Expo Client build request disallowed. Reason: ${errorMessage}`);
}
const bundleIdentifier = (0, _generateBundleIdentifier().default)(authData.team.id);
const experienceName = await (0, _clientBuildApi().getExperienceName)({
user,
appleTeamId: authData.team.id
});
const context = { ...authData,
bundleIdentifier,
experienceName,
username: user ? user.username : null
};
await appleApi().ensureAppExists(context, {
enablePushNotifications: true
});
const {
devices
} = await (0, _fastlane().runAction)(_fastlane().travelingFastlane.listDevices, ['--all-ios-profile-devices', context.appleId, context.appleIdPassword, context.team.id]);
const udids = devices.map(device => device.deviceNumber);
const distributionCert = await (0, _selectDistributionCert().default)(context);
const pushKey = await (0, _selectPushKey().default)(context);
const provisioningProfile = await (0, _selectAdhocProvisioningProfile().default)(context, udids, distributionCert.distCertSerialNumber); // push notifications won't work if we dont have any push creds
// we also dont store anonymous creds, so user needs to be logged in
if (pushKey === null || !user) {
const disabledReason = pushKey === null ? 'you did not upload your push credentials' : 'we require you to be logged in to store push credentials'; // TODO(quin): remove this when we fix push notifications
// keep the default push notification reason if we haven't implemented API tokens
disabledServices.pushNotifications.reason = disabledServices.pushNotifications.reason || disabledReason;
}
if (Object.keys(disabledServices).length > 0) {
_log().default.newLine();
_log().default.warn('These services will be disabled in your custom Expo Client:');
const table = new (_cliTable().default)({
head: ['Service', 'Reason'],
style: {
head: ['cyan']
}
});
table.push(...Object.keys(disabledServices).map(serviceKey => {
const service = disabledServices[serviceKey];
return [service.name, service.reason];
}));
(0, _log().default)(table.toString());
(0, _log().default)('See https://docs.expo.io/versions/latest/guides/adhoc-builds/#optional-additional-configuration-steps for more details.');
} // if user is logged in, then we should update credentials
const credentialsList = [distributionCert, pushKey, provisioningProfile].filter(i => i);
if (user) {
// store all the credentials that we mark for update
const updateCredentialsFn = async listOfCredentials => {
if (listOfCredentials.length === 0) {
return;
}
const credentials = listOfCredentials.reduce((acc, credential) => {
return { ...acc,
...credential
};
}, {
teamId: context.team.id
});
await _xdl().Credentials.updateCredentialsForPlatform(IOS, credentials, [], {
username: user.username,
experienceName,
bundleIdentifier
});
};
const CredentialsUpdater = new (_tagger().Updater)(updateCredentialsFn);
await CredentialsUpdater.updateAllAsync(credentialsList);
} else {
// clear update tags, we dont store credentials for anonymous users
(0, _tagger().clearTags)(credentialsList);
}
let email;
if (user) {
email = user.email;
} else {
({
email
} = await (0, _prompt().default)({
name: 'email',
message: 'Please enter an email address to notify, when the build is completed:',
filter: value => value.trim(),
validate: value => /.+@.+/.test(value) ? true : "That doesn't look like a valid email."
}));
}
_log().default.newLine();
let addUdid;
if (udids.length === 0) {
(0, _log().default)('There are no devices registered to your Apple Developer account. Please follow the instructions below to register an iOS device.');
addUdid = true;
} else {
(0, _log().default)('Custom builds of the Expo Client can only be installed on devices which have been registered with Apple at build-time.');
(0, _log().default)('These devices are currently registered on your Apple Developer account:');
const table = new (_cliTable().default)({
head: ['Name', 'Identifier'],
style: {
head: ['cyan']
}
});
table.push(...devices.map(device => [device.name, device.deviceNumber]));
(0, _log().default)(table.toString());
const udidPrompt = await (0, _prompt().default)({
name: 'addUdid',
message: 'Would you like to register a new device to use the Expo Client with?',
type: 'confirm',
default: true
});
addUdid = udidPrompt.addUdid;
}
const result = await (0, _clientBuildApi().createClientBuildRequest)({
user,
context,
distributionCert,
provisioningProfile,
pushKey,
udids,
addUdid,
email,
customAppConfig: exp
});
_log().default.newLine();
if (addUdid) {
_urlOpts().default.printQRCode(result.registrationUrl);
(0, _log().default)('Open the following link on your iOS device (or scan the QR code) and follow the instructions to install the development profile:');
_log().default.newLine();
(0, _log().default)(_chalk().default.green(`${result.registrationUrl}`));
_log().default.newLine();
(0, _log().default)('Please note that you can only register one iOS device per request.');
(0, _log().default)("After you register your device, we'll start building your client, and you'll receive an email when it's ready to install.");
} else {
_urlOpts().default.printQRCode(result.statusUrl);
(0, _log().default)('Your custom Expo Client is being built! 🛠');
(0, _log().default)('Open this link on your iOS device (or scan the QR code) to view build logs and install the client:');
_log().default.newLine();
(0, _log().default)(_chalk().default.green(`${result.statusUrl}`));
}
_log().default.newLine();
}, true);
program.command('client:install:ios').description('Install the latest version of Expo Client for iOS on the simulator').asyncAction(async () => {
if (await _xdl().Simulator.upgradeExpoAsync()) {
(0, _log().default)('Done!');
}
}, true);
program.command('client:install:android').description('Install the latest version of Expo Client for Android on a connected device or emulator').asyncAction(async () => {
if (await _xdl().Android.upgradeExpoAsync()) {
(0, _log().default)('Done!');
}
}, true);
};
exports.default = _default;
//# sourceMappingURL=../../__sourcemaps__/commands/client/index.js.map