Skip to content

Commit

Permalink
[expotool] improve generate-bare-app tooling (expo#17816)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajsmth authored Jul 11, 2022
1 parent 4ca724b commit a5cee38
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 18 deletions.
29 changes: 29 additions & 0 deletions template-files/generate-bare-app/scripts/addPackages.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ function symlinkPackages(expoDirectory, projectDirectory, packageNames) {
if (!symlinks.includes(packageName)) {
symlinks.push(packageName);
}

// add any dependencies of the specified packages if they are not already symlinked
const dependencies = getPackageDependencies({ packageName });
dependencies.forEach((dependency) => {
if (!symlinks.includes(dependency)) {
symlinks.push(dependency);
}
});
});

symlinks.forEach((packageName) => {
Expand All @@ -36,6 +44,27 @@ function symlinkPackages(expoDirectory, projectDirectory, packageNames) {
{ encoding: 'utf-8' }
);

function getPackageDependencies({ packageName }) {
const packagePath = path.resolve(expoDirectory, 'packages', packageName, 'package.json');

if (!fs.existsSync(packagePath)) {
return [];
}

const dependencies = new Set([packageName]);

const pkg = require(packagePath);

if (pkg.dependencies) {
Object.keys(pkg.dependencies).forEach((dependency) => {
const deps = getPackageDependencies({ packageName: dependency });
deps.forEach((dep) => dependencies.add(dep));
});
}

return Array.from(dependencies);
}

console.log('Symlinking packages complete');
}

Expand Down
4 changes: 2 additions & 2 deletions tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@types/diff": "^5.0.2",
"@types/folder-hash": "^4.0.1",
"@types/fs-extra": "^9.0.13",
"@types/diff": "^5.0.2",
"@types/http-proxy": "^1.17.8",
"@types/inquirer": "^8.2.1",
"@types/ip": "^1.1.0",
"@types/klaw-sync": "^6.0.1",
"@types/node": "^14.18.12",
"@types/node": "16.11.43",
"@types/node-fetch": "^2.6.1",
"@types/semver": "^7.3.9",
"@types/uuid": "^3.4.4",
Expand Down
63 changes: 49 additions & 14 deletions tools/src/commands/GenerateBareApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import path from 'path';

import { EXPO_DIR, PACKAGES_DIR } from '../Constants';
import { runExpoCliAsync } from '../ExpoCLI';
import { GitDirectory } from '../Git';

export type GenerateBareAppOptions = {
name?: string;
template?: string;
clean?: boolean;
localTemplate?: boolean;
outDir?: string;
rnVersion?: string;
};
Expand All @@ -20,6 +22,7 @@ export async function action(
name: appName = 'my-generated-bare-app',
outDir = 'bare-apps',
template = 'expo-template-bare-minimum',
localTemplate = false,
clean = false,
rnVersion,
}: GenerateBareAppOptions
Expand All @@ -32,17 +35,22 @@ export async function action(

const packagesToSymlink = await getPackagesToSymlink({ packageNames, workspaceDir });

await createProjectDirectory({ clean, projectDir, workspaceDir, appName, template });
await cleanIfNeeded({ clean, projectDir, workspaceDir });
await createProjectDirectory({ workspaceDir, appName, template, localTemplate });
await modifyPackageJson({ packagesToSymlink, projectDir });
await modifyAppJson({ projectDir, appName });
await yarnInstall({ projectDir });
await symlinkPackages({ packagesToSymlink, projectDir });
await runExpoPrebuild({ projectDir });
await updateRNVersion({ projectDir, rnVersion });
if (rnVersion != null) {
await updateRNVersion({ rnVersion, projectDir });
}
await createMetroConfig({ projectRoot: projectDir });
await createScripts({ projectDir });

// reestablish symlinks - some might be wiped out from prebuild
await symlinkPackages({ projectDir, packagesToSymlink });
await stageAndCommitInitialChanges({ projectDir });

console.log(`Project created in ${projectDir}!`);
}
Expand All @@ -60,27 +68,31 @@ export function getDirectories({
};
}

async function cleanIfNeeded({ workspaceDir, projectDir, clean }) {
console.log('Creating project');

await fs.mkdirs(workspaceDir);

if (clean) {
await fs.remove(projectDir);
}
}

async function createProjectDirectory({
clean,
workspaceDir,
projectDir,
appName,
template,
localTemplate,
}: {
clean: boolean;
workspaceDir: string;
projectDir: string;
appName: string;
template: string;
localTemplate: boolean;
}) {
console.log('Creating project');

if (!fs.existsSync(workspaceDir)) {
fs.mkdirSync(workspaceDir);
}

if (clean) {
await fs.remove(projectDir);
if (localTemplate) {
const pathToBareTemplate = path.resolve(EXPO_DIR, 'templates', 'expo-template-bare-minimum');
const pathToWorkspace = path.resolve(workspaceDir, appName);
return fs.copy(pathToBareTemplate, pathToWorkspace, { recursive: true });
}

return await runExpoCliAsync('init', [appName, '--no-install', '--template', template], {
Expand Down Expand Up @@ -291,6 +303,24 @@ async function createScripts({ projectDir }) {
console.log('Added package scripts!');
}

async function stageAndCommitInitialChanges({ projectDir }) {
const gitDirectory = new GitDirectory(projectDir);
await gitDirectory.initAsync();
await gitDirectory.addFilesAsync(['.']);
await gitDirectory.commitAsync({ title: 'Initialized bare app!' });
}

async function modifyAppJson({ projectDir, appName }: { projectDir: string; appName: string }) {
const pathToAppJson = path.resolve(projectDir, 'app.json');
const json = await fs.readJson(pathToAppJson);

const strippedAppName = appName.replaceAll('-', '');
json.expo.android = { package: `com.${strippedAppName}` };
json.expo.ios = { bundleIdentifier: `com.${strippedAppName}` };

await fs.writeJSON(pathToAppJson, json, { spaces: 2 });
}

export default (program: Command) => {
program
.command('generate-bare-app [packageNames...]')
Expand All @@ -300,6 +330,11 @@ export default (program: Command) => {
.option('--rnVersion <string>', 'Version of react-native to include')
.option('-o, --outDir <string>', 'Specifies the directory to build the project in')
.option('-t, --template <string>', 'Specify the expo template to use as the project starter')
.option(
'--localTemplate',
'Copy the localTemplate expo-template-bare-minimum from the expo repo',
false
)
.description(`Generates a bare app with the specified packages symlinked`)
.asyncAction(action);
};
2 changes: 1 addition & 1 deletion tools/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "es2018",
"lib": ["es2018", "esnext.asynciterable"],
"lib": ["es2021", "esnext.asynciterable"],
"module": "commonjs",
"sourceMap": true,
"inlineSources": true,
Expand Down
7 changes: 6 additions & 1 deletion tools/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2239,11 +2239,16 @@
"@types/node" "*"
form-data "^3.0.0"

"@types/node@*", "@types/node@>= 8", "@types/node@^14.18.12":
"@types/node@*", "@types/node@>= 8":
version "14.18.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24"
integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==

"@types/[email protected]":
version "16.11.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.43.tgz#555e5a743f76b6b897d47f945305b618525ddbe6"
integrity sha512-GqWykok+3uocgfAJM8imbozrqLnPyTrpFlrryURQlw1EesPUCx5XxTiucWDSFF9/NUEXDuD4bnvHm8xfVGWTpQ==

"@types/q@^1.5.1":
version "1.5.2"
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
Expand Down

0 comments on commit a5cee38

Please sign in to comment.