Skip to content

Commit

Permalink
fix(expo): update package.json eas build scripts to fix eas build (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
xiongemi authored May 9, 2023
1 parent c8688a6 commit ad77b91
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 3 deletions.
6 changes: 6 additions & 0 deletions packages/expo/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
"version": "16.0.0-beta.1",
"description": "Replace @nrwl/expo with @nx/expo",
"implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages"
},
"update-eas-scripts": {
"cli": "nx",
"version": "16.1.4-beta.0",
"description": "Update package.json eas build lifecycle scripts",
"implementation": "./src/migrations/update-16-1-4/update-eas-scripts"
}
},
"packageJsonUpdates": {
Expand Down
2 changes: 2 additions & 0 deletions packages/expo/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import initGenerator from '../init/init';
import { addProject } from './lib/add-project';
import { addDetox } from './lib/add-detox';
import { createApplicationFiles } from './lib/create-application-files';
import { addEasScripts } from './lib/add-eas-scripts';
import { Schema } from './schema';

export async function expoApplicationGenerator(
Expand Down Expand Up @@ -45,6 +46,7 @@ export async function expoApplicationGenerator(
);
const detoxTask = await addDetox(host, options);
const symlinkTask = runSymlink(host.root, options.appProjectRoot);
addEasScripts(host);

if (!options.skipFormat) {
await formatFiles(host);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"react-native-web": "*"
},
"scripts": {
<% if (packageManager === 'npm') { %>"eas-build-pre-install": "cd <%= offsetFromRoot %> && cp <%= packageLockFile %> ./<%= appProjectRoot %>/", <% } %>
"postinstall": "rm -r node_modules && cd <%= offsetFromRoot %> && <%= packageManager %> install && npx nx sync-deps <%= projectName %> && npx nx ensure-symlink <%= projectName %>"
"eas-build-pre-install": "cd <%= offsetFromRoot %> && node tools/scripts/eas-build-pre-install.mjs . <%= appProjectRoot %> && cp <%= packageLockFile %> <%= appProjectRoot %>",
"eas-build-post-install": "cd <%= offsetFromRoot %> && node tools/scripts/eas-build-post-install.mjs . <%= appProjectRoot %>"
}
}
75 changes: 75 additions & 0 deletions packages/expo/src/generators/application/lib/add-eas-scripts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { Tree } from '@nx/devkit';

const preInstallScript = `
/*
* This script is used to patch the '@nx/expo' package to work with EAS Build.
* It is run as the eas-build-pre-install script in the 'package.json' of expo app.
* It is executed as 'node tools/scripts/eas-build-pre-install.mjs <workspace root> <project root>'
* It will copy the dependencies and devDependencies from the workspace package.json to project's package.json.
* This is needed because EAS Build does the install in project's directory and not workspace's directory.
*/
import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
const [workspaceRoot, projectRoot] = process.argv.slice(2);
if (!workspaceRoot) {
throw new Error('Missing workspace root');
}
if (!projectRoot) {
throw new Error('Missing project root');
}
try {
const workspacePackage = JSON.parse(
readFileSync(join(workspaceRoot, 'package.json')).toString()
);
const projectPackage = JSON.parse(
readFileSync(join(projectRoot, 'package.json')).toString()
);
projectPackage.dependencies = workspacePackage.dependencies;
projectPackage.devDependencies = workspacePackage.devDependencies;
writeFileSync(
join(projectRoot, 'package.json'),
JSON.stringify(projectPackage, null, 2)
);
} catch (e) {
console.error('Error reading package.json file', e);
}
`;

const postInstallScript = `
/**
* This script is used to patch the '@nx/expo' package to work with EAS Build.
* It is run as a eas-build-post-install script in the 'package.json' of expo app.
* It is executed as 'node tools/scripts/eas-build-post-install.mjs <workspace root> <project root>'
* It will create a symlink from the project's node_modules to the workspace's node_modules.
*/
import { symlink, existsSync } from 'fs';
import { join } from 'path';
const [workspaceRoot, projectRoot] = process.argv.slice(2);
if (existsSync(join(workspaceRoot, 'node_modules'))) {
console.log('Symlink already exists');
process.exit(0);
}
symlink(join(projectRoot, 'node_modules'), join(workspaceRoot, 'node_modules'), 'dir', (err) => {
if (err) console.log(err);
else {
console.log('Symlink created');
}
});
`;

export function addEasScripts(tree: Tree) {
const preInstallScriptPath = 'tools/scripts/eas-build-pre-install.mjs';
const postInstallScriptPath = 'tools/scripts/eas-build-post-install.mjs';

if (!tree.exists(preInstallScriptPath)) {
tree.write(preInstallScriptPath, preInstallScript);
}
if (!tree.exists(postInstallScriptPath)) {
tree.write(postInstallScriptPath, postInstallScript);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
Tree,
addProjectConfiguration,
readJson,
updateJson,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import update from './update-eas-scripts';

describe('update-eas-scripts', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();

addProjectConfiguration(tree, 'products', {
root: 'apps/products',
sourceRoot: 'apps/products/src',
targets: {
start: {
executor: '@nrwl/expo:start',
},
},
});
tree.write('apps/products/package.json', JSON.stringify({}));
});

it('should add scripts', async () => {
update(tree);

expect(tree.exists('tools/scripts/eas-build-pre-install.mjs')).toBeTruthy();
expect(
tree.exists('tools/scripts/eas-build-post-install.mjs')
).toBeTruthy();
const packageJson = readJson(tree, 'apps/products/package.json');
expect(packageJson.scripts['eas-build-pre-install']).toEqual(
'cd ../../ && node tools/scripts/eas-build-pre-install.mjs . apps/products && cp package-lock.json apps/products'
);
expect(packageJson.scripts['eas-build-post-install']).toEqual(
'cd ../../ && node tools/scripts/eas-build-post-install.mjs . apps/products'
);
});

it('should remove postinstall script', async () => {
updateJson(tree, 'apps/products/package.json', (json) => {
json.scripts = {
postinstall: 'some script',
};
return json;
});
update(tree);

const packageJson = readJson(tree, 'apps/products/package.json');
expect(packageJson.scripts['postinstall']).toBeUndefined();
});
});
47 changes: 47 additions & 0 deletions packages/expo/src/migrations/update-16-1-4/update-eas-scripts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {
PackageManager,
Tree,
detectPackageManager,
getProjects,
logger,
offsetFromRoot,
updateJson,
} from '@nx/devkit';
import { addEasScripts } from '../../generators/application/lib/add-eas-scripts';
import { join } from 'path';

/**
* Update app's package.json to use eas-build-pre-install and eas-build-post-install scripts.
*/
export default function update(tree: Tree) {
const projects = getProjects(tree);
const packageManagerLockFile: Record<PackageManager, string> = {
npm: 'package-lock.json',
yarn: 'yarn.lock',
pnpm: 'pnpm-lock.yaml',
};

for (const [name, config] of projects.entries()) {
if (config.targets?.['start']?.executor === '@nrwl/expo:start') {
try {
addEasScripts(tree);
updateJson(tree, join(config.root, 'package.json'), (packageJson) => {
if (packageJson.scripts?.['postinstall']) {
delete packageJson.scripts['postinstall'];
}
const packageManager = detectPackageManager(tree.root);
const packageLockFile = packageManagerLockFile[packageManager];
const offset = offsetFromRoot(config.root);
packageJson.scripts = {
...packageJson.scripts,
'eas-build-pre-install': `cd ${offset} && node tools/scripts/eas-build-pre-install.mjs . ${config.root} && cp ${packageLockFile} ${config.root}`,
'eas-build-post-install': `cd ${offset} && node tools/scripts/eas-build-post-install.mjs . ${config.root}`,
};
return packageJson;
});
} catch {
logger.error(`Unable to update package.json for project ${name}.`);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function runCliBuild(
*/
childProcess = fork(
join(workspaceRoot, './node_modules/react-native/cli.js'),
['run-android', ...createBuildAndroidOptions(options), '--no-packager'],
['build-android', ...createBuildAndroidOptions(options), '--no-packager'],
{
cwd: join(workspaceRoot, projectRoot),
env: { ...process.env, RCT_METRO_PORT: options.port.toString() },
Expand Down

0 comments on commit ad77b91

Please sign in to comment.