Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

Commit

Permalink
Prompt for bundle ID and package name in expo apply (#2498)
Browse files Browse the repository at this point in the history
* Prompt for bundle ID and package name in expo apply

* Work in projects without an expo config
  • Loading branch information
EvanBacon authored Aug 26, 2020
1 parent 4aab89e commit 9e58cdb
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 15 deletions.
37 changes: 33 additions & 4 deletions packages/expo-cli/src/commands/apply.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { getConfig } from '@expo/config';
import JsonFile from '@expo/json-file';
import chalk from 'chalk';
import { Command } from 'commander';
import path from 'path';

import configureAndroidProjectAsync from './apply/configureAndroidProjectAsync';
import configureIOSProjectAsync from './apply/configureIOSProjectAsync';
Expand All @@ -9,6 +13,29 @@ type Options = {
// todo: probably let people pass an ios or android directory in case they don't follow the convention
};

async function ensureConfigExistsAsync(projectRoot: string): Promise<void> {
try {
const config = getConfig(projectRoot, { skipSDKVersionRequirement: true });
// If no config exists in the file system then we should generate one so the process doesn't fail.
if (!config.dynamicConfigPath && !config.staticConfigPath) {
// Don't check for a custom config path because the process should fail if a custom file doesn't exist.
// Write the generated config.
// writeConfigJsonAsync(projectRoot, config.exp);
await JsonFile.writeAsync(
path.join(projectRoot, 'app.json'),
{ expo: config.exp },
{ json5: false }
);
}
} catch (error) {
// TODO(Bacon): Currently this is already handled in the command
console.log();
console.log(chalk.red(error.message));
console.log();
process.exit(1);
}
}

export default function (program: Command) {
program
.command('apply [project-dir]')
Expand All @@ -22,14 +49,16 @@ export default function (program: Command) {
'Take the configuration from app.json or app.config.js and apply it to a native project.'
)
.asyncActionProjectDir(async (projectDir: string, options: Options) => {
if (!options.platform || options.platform === 'ios') {
await configureIOSProjectAsync(projectDir);
logConfigWarningsIOS();
}
await ensureConfigExistsAsync(projectDir);

if (!options.platform || options.platform === 'android') {
await configureAndroidProjectAsync(projectDir);
logConfigWarningsAndroid();
}

if (!options.platform || options.platform === 'ios') {
await configureIOSProjectAsync(projectDir);
logConfigWarningsIOS();
}
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import fs from 'fs-extra';
import { sync as globSync } from 'glob';
import path from 'path';

import { getOrPromptForPackage } from '../eject/ConfigValidation';

async function modifyBuildGradleAsync(
projectRoot: string,
callback: (buildGradle: string) => string
Expand Down Expand Up @@ -54,6 +56,9 @@ async function modifyMainActivityJavaAsync(
}

export default async function configureAndroidProjectAsync(projectRoot: string) {
// Check package before reading the config because it may mutate the config if the user is prompted to define it.
await getOrPromptForPackage(projectRoot);

const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true });
const username = await UserManager.getCurrentUsernameAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { getProjectName } from '@expo/config/build/ios/utils/Xcodeproj';
import { IosPlist, UserManager } from '@expo/xdl';
import path from 'path';

import { getOrPromptForBundleIdentifier } from '../eject/ConfigValidation';

export default async function configureIOSProjectAsync(projectRoot: string) {
// Check bundle ID before reading the config because it may mutate the config if the user is prompted to define it.
const bundleIdentifier = await getOrPromptForBundleIdentifier(projectRoot);
IOSConfig.BundleIdenitifer.setBundleIdentifierForPbxproj(projectRoot, bundleIdentifier);

const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true });
const username = await UserManager.getCurrentUsernameAsync();

IOSConfig.BundleIdenitifer.setBundleIdentifierForPbxproj(projectRoot, exp.ios!.bundleIdentifier!);
IOSConfig.Google.setGoogleServicesFile(exp, projectRoot);
IOSConfig.DeviceFamily.setDeviceFamily(exp, projectRoot);

Expand Down
33 changes: 23 additions & 10 deletions packages/expo-cli/src/commands/eject/ConfigValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function validatePackage(value: string): boolean {
}

export async function getOrPromptForBundleIdentifier(projectRoot: string): Promise<string> {
const { exp } = getConfig(projectRoot);
const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true });

const currentBundleId = exp.ios?.bundleIdentifier;
if (currentBundleId) {
Expand Down Expand Up @@ -77,15 +77,20 @@ export async function getOrPromptForBundleIdentifier(projectRoot: string): Promi
}
);

await attemptModification(projectRoot, `Your iOS bundle identifier is now: ${bundleIdentifier}`, {
ios: { bundleIdentifier },
});
await attemptModification(
projectRoot,
`Your iOS bundle identifier is now: ${bundleIdentifier}`,
{
ios: { ...(exp.ios || {}), bundleIdentifier },
},
{ ios: { bundleIdentifier } }
);

return bundleIdentifier;
}

export async function getOrPromptForPackage(projectRoot: string): Promise<string> {
const { exp } = getConfig(projectRoot);
const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true });

const currentPackage = exp.android?.package;
if (currentPackage) {
Expand Down Expand Up @@ -142,17 +147,25 @@ export async function getOrPromptForPackage(projectRoot: string): Promise<string
}
);

await attemptModification(projectRoot, `Your Android package is now: ${packageName}`, {
android: { package: packageName },
});
await attemptModification(
projectRoot,
`Your Android package is now: ${packageName}`,
{
android: { ...(exp.android || {}), package: packageName },
},
{
android: { package: packageName },
}
);

return packageName;
}

async function attemptModification(
projectRoot: string,
modificationSuccessMessage: string,
edits: Partial<ExpoConfig>
edits: Partial<ExpoConfig>,
exactEdits: Partial<ExpoConfig>
): Promise<void> {
const modification = await modifyConfigAsync(projectRoot, edits, {
skipSDKVersionRequirement: true,
Expand All @@ -162,7 +175,7 @@ async function attemptModification(
log(modificationSuccessMessage);
log.newLine();
} else {
warnAboutConfigAndExit(modification.type, modification.message!, edits);
warnAboutConfigAndExit(modification.type, modification.message!, exactEdits);
}
}

Expand Down

0 comments on commit 9e58cdb

Please sign in to comment.