Skip to content

Commit

Permalink
feat(react-native): generate pod install target (#21166)
Browse files Browse the repository at this point in the history
  • Loading branch information
xiongemi authored Jan 16, 2024
1 parent e38b0bb commit 78a4df8
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 32 deletions.
45 changes: 44 additions & 1 deletion e2e/expo/src/expo-pcv3.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import {
runCommandUntil,
killProcessAndPorts,
checkFilesExist,
updateFile,
runCLIAsync,
} from 'e2e/utils';
import { join } from 'path';

describe('@nx/expo/plugin', () => {
let project: string;
Expand Down Expand Up @@ -54,7 +57,7 @@ describe('@nx/expo/plugin', () => {

try {
process = await runCommandUntil(
`start ${appName} --port=${port}`,
`start ${appName} -- --port=${port}`,
(output) => output.includes(`http://localhost:8081`)
);
} catch (err) {
Expand All @@ -66,4 +69,44 @@ describe('@nx/expo/plugin', () => {
await killProcessAndPorts(process.pid, port);
}
});

it('should serve the app', async () => {
let process: ChildProcess;
const port = 8081;

try {
process = await runCommandUntil(
`serve ${appName} -- --port=${port}`,
(output) => output.includes(`http://localhost:8081`)
);
} catch (err) {
console.error(err);
}

// port and process cleanup
if (process && process.pid) {
await killProcessAndPorts(process.pid, port);
}
});

it('should prebuild', async () => {
// run prebuild command with git check disable
// set a mock package name for ios and android in expo's app.json
const appJsonPath = join(appName, `app.json`);
const appJson = await readJson(appJsonPath);
if (appJson.expo.ios) {
appJson.expo.ios.bundleIdentifier = 'nx.test';
}
if (appJson.expo.android) {
appJson.expo.android.package = 'nx.test';
}
updateFile(appJsonPath, JSON.stringify(appJson));

// run prebuild command with git check disable
process.env['EXPO_NO_GIT_STATUS'] = 'true';
const prebuildResult = await runCLIAsync(
`prebuild ${appName} --no-interactive --install=false`
);
expect(prebuildResult.combinedOutput).toContain('Config synced');
});
});
2 changes: 1 addition & 1 deletion e2e/react-native/src/react-native-pcv3.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('@nx/react-native/plugin', () => {
newProject();
appName = uniq('app');
runCLI(
`generate @nx/react-native:app ${appName} --project-name-and-root-format=as-provided --no-interactive`,
`generate @nx/react-native:app ${appName} --project-name-and-root-format=as-provided --install=false --no-interactive`,
{ env: { NX_PCV3: 'true' } }
);
});
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-native/src/react-native.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ describe('react native', () => {
const libName = uniq('@my-org/lib1');

runCLI(
`generate @nx/react-native:application ${appName} --project-name-and-root-format=as-provided --no-interactive`
`generate @nx/react-native:application ${appName} --project-name-and-root-format=as-provided --install=false --no-interactive`
);

// check files are generated without the layout directory ("apps/") and
Expand Down
23 changes: 11 additions & 12 deletions packages/expo/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';

export interface ExpoPluginOptions {
startTargetName?: string;
serveTargetName?: string;
runIosTargetName?: string;
runAndroidTargetName?: string;
exportTargetName?: string;
Expand Down Expand Up @@ -67,7 +68,6 @@ export const createNodes: CreateNodes<ExpoPluginOptions> = [
const siblingFiles = readdirSync(join(context.workspaceRoot, projectRoot));
if (
!siblingFiles.includes('package.json') ||
!siblingFiles.includes('project.json') ||
!siblingFiles.includes('metro.config.js')
) {
return {};
Expand Down Expand Up @@ -107,16 +107,17 @@ function buildExpoTargets(

const targets: Record<string, TargetConfiguration> = {
[options.startTargetName]: {
command: `expo start`,
executor: `@nx/expo:start`,
},
[options.serveTargetName]: {
command: `expo start --web`,
options: { cwd: projectRoot },
},
[options.runIosTargetName]: {
command: `expo run:ios`,
options: { cwd: projectRoot },
executor: `@nx/expo:run-ios`,
},
[options.runAndroidTargetName]: {
command: `expo run:android`,
options: { cwd: projectRoot },
executor: `@nx/expo:run-android`,
},
[options.exportTargetName]: {
command: `expo export`,
Expand All @@ -139,18 +140,15 @@ function buildExpoTargets(
options: { cwd: workspaceRoot }, // install at workspace root
},
[options.prebuildTargetName]: {
command: `expo prebuild`,
options: { cwd: projectRoot },
executor: `@nx/expo:prebuild`,
},
[options.buildTargetName]: {
command: `eas build`,
options: { cwd: projectRoot },
executor: `@nx/expo:build`,
dependsOn: [`^${options.buildTargetName}`],
inputs: getInputs(namedInputs),
},
[options.submitTargetName]: {
command: `eas submit`,
options: { cwd: projectRoot },
executor: `@nx/expo:submit`,
dependsOn: [`^${options.submitTargetName}`],
inputs: getInputs(namedInputs),
},
Expand Down Expand Up @@ -208,6 +206,7 @@ function load(path: string): any {
function normalizeOptions(options: ExpoPluginOptions): ExpoPluginOptions {
options ??= {};
options.startTargetName ??= 'start';
options.serveTargetName ??= 'serve';
options.runIosTargetName ??= 'run-ios';
options.runAndroidTargetName ??= 'run-android';
options.exportTargetName ??= 'export';
Expand Down
8 changes: 3 additions & 5 deletions packages/expo/src/generators/application/lib/add-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import {
TargetConfiguration,
Tree,
} from '@nx/devkit';

import { hasExpoPlugin } from '../../../utils/has-expo-plugin';
import { NormalizedSchema } from './normalize-options';

export function addProject(host: Tree, options: NormalizedSchema) {
const nxJson = readNxJson(host);
const hasPlugin = nxJson.plugins?.some((p) =>
typeof p === 'string'
? p === '@nx/expo/plugin'
: p.plugin === '@nx/expo/plugin'
);
const hasPlugin = hasExpoPlugin(host);

const projectConfiguration: ProjectConfiguration = {
root: options.appProjectRoot,
Expand Down
13 changes: 4 additions & 9 deletions packages/expo/src/generators/init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
reactNativeVersion,
reactVersion,
} from '../../utils/versions';
import { hasExpoPlugin } from '../../utils/has-expo-plugin';
import { addGitIgnoreEntry } from './lib/add-git-ignore-entry';
import { Schema } from './schema';

Expand Down Expand Up @@ -64,18 +65,12 @@ function moveDependency(host: Tree) {

function addPlugin(host: Tree) {
const nxJson = readNxJson(host);
nxJson.plugins ??= [];

for (const plugin of nxJson.plugins) {
if (
typeof plugin === 'string'
? plugin === '@nx/expo/plugin'
: plugin.plugin === '@nx/expo/plugin'
) {
return;
}
if (hasExpoPlugin(host)) {
return;
}

nxJson.plugins ??= [];
nxJson.plugins.push({
plugin: '@nx/expo/plugin',
options: {
Expand Down
10 changes: 10 additions & 0 deletions packages/expo/src/utils/has-expo-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { readNxJson, Tree } from '@nx/devkit';

export function hasExpoPlugin(tree: Tree) {
const nxJson = readNxJson(tree);
return !!nxJson.plugins?.some((p) =>
typeof p === 'string'
? p === '@nx/expo/plugin'
: p.plugin === '@nx/expo/plugin'
);
}
17 changes: 14 additions & 3 deletions packages/react-native/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
CreateNodes,
CreateNodesContext,
detectPackageManager,
joinPathFragments,
NxJsonConfiguration,
readJsonFile,
TargetConfiguration,
Expand All @@ -17,6 +18,7 @@ import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';

export interface ReactNativePluginOptions {
startTargetName?: string;
podInstallTargetName?: string;
runIosTargetName?: string;
runAndroidTargetName?: string;
buildIosTargetName?: string;
Expand Down Expand Up @@ -63,7 +65,6 @@ export const createNodes: CreateNodes<ReactNativePluginOptions> = [
const siblingFiles = readdirSync(join(context.workspaceRoot, projectRoot));
if (
!siblingFiles.includes('package.json') ||
!siblingFiles.includes('project.json') ||
!siblingFiles.includes('metro.config.js')
) {
return {};
Expand Down Expand Up @@ -102,8 +103,17 @@ function buildReactNativeTargets(

const targets: Record<string, TargetConfiguration> = {
[options.startTargetName]: {
command: `react-native start`,
options: { cwd: projectRoot },
executor: `@nx/react-native:start`,
},
[options.podInstallTargetName]: {
command: `pod install`,
options: { cwd: joinPathFragments(projectRoot, 'ios') },
cache: true,
inputs: getInputs(namedInputs),
outputs: [
getOutputs(projectRoot, 'ios/Pods'),
getOutputs(projectRoot, 'ios/Podfile.lock'),
],
},
[options.runIosTargetName]: {
command: `react-native run-ios`,
Expand Down Expand Up @@ -191,6 +201,7 @@ function normalizeOptions(
): ReactNativePluginOptions {
options ??= {};
options.startTargetName ??= 'start';
options.podInstallTargetName ??= 'pod-install';
options.runIosTargetName ??= 'run-ios';
options.runAndroidTargetName ??= 'run-android';
options.buildIosTargetName ??= 'build-ios';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { runSymlink } from '../../utils/symlink-task';
import { addLinting } from '../../utils/add-linting';
import { addJest } from '../../utils/add-jest';
import { chmodAndroidGradlewFilesTask } from '../../utils/chmod-android-gradle-files';
import { runPodInstall } from '../../utils/pod-install-task';

import { normalizeOptions } from './lib/normalize-options';
import initGenerator from '../init/init';
Expand Down Expand Up @@ -79,6 +80,13 @@ export async function reactNativeApplicationGeneratorInternal(
);
tasks.push(chmodTaskGradlewTask);

const podInstallTask = runPodInstall(
joinPathFragments(host.root, options.iosProjectRoot)
);
if (options.install) {
tasks.push(podInstallTask);
}

if (!options.skipFormat) {
await formatFiles(host);
}
Expand Down
1 change: 1 addition & 0 deletions packages/react-native/src/generators/init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ function addPlugin(host: Tree) {
plugin: '@nx/react-native/plugin',
options: {
startTargetName: 'start',
podInstallTargetName: 'pod-install',
bundleTargetName: 'bundle',
runIosTargetName: 'run-ios',
runAndroidTargetName: 'run-android',
Expand Down

0 comments on commit 78a4df8

Please sign in to comment.