From f40353fcc4efac1c0bb35435750d94f06088032c Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 08:51:20 +0500 Subject: [PATCH 01/35] refactor: properly handle invalid template package --- packages/cli/src/commands/init/template.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/commands/init/template.ts b/packages/cli/src/commands/init/template.ts index 02e6831ba..a7640a516 100644 --- a/packages/cli/src/commands/init/template.ts +++ b/packages/cli/src/commands/init/template.ts @@ -4,6 +4,7 @@ import {logger} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import copyFiles from '../../tools/copyFiles'; import replacePathSepForRegex from '../../tools/replacePathSepForRegex'; +import fs from 'fs-extra'; export type TemplateConfig = { placeholderName: string; @@ -37,7 +38,11 @@ export function getTemplateConfig( ); logger.debug(`Getting config from ${configFilePath}.js`); - + if (!fs.existsSync(configFilePath)) { + throw new Error( + `Invalid template '${templateName}' specified. Make sure the template is CLI v2 compliant i.e. has a 'template.config.js' file.`, + ); + } return require(configFilePath); } From 710d8fb372f1d6206b17acf834980e9d2e59442c Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 09:41:26 +0500 Subject: [PATCH 02/35] refactor: error checks when getting template name --- .../cli/src/commands/init/templateName.ts | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/commands/init/templateName.ts b/packages/cli/src/commands/init/templateName.ts index 8a8fcb558..7e649cedb 100644 --- a/packages/cli/src/commands/init/templateName.ts +++ b/packages/cli/src/commands/init/templateName.ts @@ -1,5 +1,6 @@ import path from 'path'; import {URL} from 'url'; +import fs from 'fs-extra'; const FILE_PROTOCOL = /file:/; const TARBALL = /\.tgz$/; @@ -12,13 +13,37 @@ function handleFileProtocol(filePath: string) { // On Windows, the pathname has an extra leading / so remove that uri = uri.substring(1); } + if (!fs.existsSync(uri)) { + throw new Error( + `Failed to retrieve package name. The specified template directory path: ${uri} does not exist or is invalid.`, + ); + } + const packageJsonPath = path.join(uri, 'package.json'); + if (!fs.existsSync(packageJsonPath)) { + throw new Error( + 'Failed to retrieve package name. We expect the template directory to include package.json file, but no such file was found.', + ); + } + const packageJson = require(packageJsonPath); + if (!packageJson.name) { + throw new Error( + `Failed to retrieve package name. We expect the package.json to include package name, e.g.: "template-name", but received: "${JSON.stringify( + packageJson, + )}"`, + ); + } return { uri, - name: require(path.join(uri, 'package.json')).name, + name: packageJson.name, }; } function handleTarball(filePath: string) { + if (!fs.existsSync(filePath)) { + throw new Error( + `Failed to retrieve tarball name. The specified tarball path: ${filePath} does not exist or is invalid.`, + ); + } const nameWithVersion = path.parse(path.basename(filePath)).name; const tarballVersionMatch = nameWithVersion.match(VERSION_POSTFIX); if (!tarballVersionMatch) { From 1c692781af48ff05c2ca1dfae347c7b993b9f2f1 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 15:12:04 +0500 Subject: [PATCH 03/35] refactor: remove duplicate exception throw --- packages/cli/src/commands/bundle/assetPathUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/commands/bundle/assetPathUtils.ts b/packages/cli/src/commands/bundle/assetPathUtils.ts index 2d7e89713..7e7676715 100644 --- a/packages/cli/src/commands/bundle/assetPathUtils.ts +++ b/packages/cli/src/commands/bundle/assetPathUtils.ts @@ -31,7 +31,7 @@ function getAndroidAssetSuffix(scale: number): string { case 4: return 'xxxhdpi'; default: - throw new Error('no such scale'); + return undefined; } } From 30b0698ce87ebf7b445128a8f9d355072cf070a6 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 15:31:47 +0500 Subject: [PATCH 04/35] refactor: check if assets dest exists --- packages/cli/src/commands/bundle/saveAssets.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/cli/src/commands/bundle/saveAssets.ts b/packages/cli/src/commands/bundle/saveAssets.ts index d9549209b..691e8b949 100644 --- a/packages/cli/src/commands/bundle/saveAssets.ts +++ b/packages/cli/src/commands/bundle/saveAssets.ts @@ -30,6 +30,12 @@ function saveAssets( return Promise.resolve(); } + if (!fs.existsSync(assetsDest)) { + let error = `The specified assets destination folder: "${assetsDest}" does not exist, stopping...`; + logger.error(error); + return Promise.reject(); + } + const getAssetDestPath = platform === 'android' ? getAssetDestPathAndroid : getAssetDestPathIOS; From e27b60b8deff2a395ec3d8958454ced84887a218 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 19:28:37 +0500 Subject: [PATCH 05/35] refactor: add error checks when upgrading --- packages/cli/src/commands/upgrade/upgrade.ts | 39 ++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/commands/upgrade/upgrade.ts b/packages/cli/src/commands/upgrade/upgrade.ts index 162644bba..e9b2b9bc1 100644 --- a/packages/cli/src/commands/upgrade/upgrade.ts +++ b/packages/cli/src/commands/upgrade/upgrade.ts @@ -13,22 +13,55 @@ const webDiffUrl = 'https://react-native-community.github.io/upgrade-helper'; const rawDiffUrl = 'https://raw.githubusercontent.com/react-native-community/rn-diff-purge/diffs/diffs'; +const isConnected = (output: string): boolean => { + // there is no reliable way of checking for internet connectivity, so we should just + // read the output from npm (to check for connectivity errors) which is faster and relatively more reliable. + return !output.includes('the host is inaccessible'); +}; + +const hasErrors = (output: string): boolean => output.includes('npm ERR'); + +const hasWarnings = (output: string): boolean => output.includes('npm WARN'); + +const checkForErrors = (output: string): void => { + if (!isConnected(output)) { + logger.error( + 'Upgrade failed. You do not seem to have an internet connection.', + ); + process.exit(); + } + + if (hasErrors(output)) { + logger.error('Upgrade failed with the following errors:', output); + process.exit(); + } + + if (hasWarnings(output)) { + logger.warn(output); + } +}; + const getLatestRNVersion = async (): Promise => { logger.info('No version passed. Fetching latest...'); - const {stdout} = await execa('npm', ['info', 'react-native', 'version']); + const {stdout, stderr} = await execa('npm', [ + 'info', + 'react-native', + 'version', + ]); + checkForErrors(stderr); return stdout; }; const getRNPeerDeps = async ( version: string, ): Promise<{[key: string]: string}> => { - const {stdout} = await execa('npm', [ + const {stdout, stderr} = await execa('npm', [ 'info', `react-native@${version}`, 'peerDependencies', '--json', ]); - + checkForErrors(stderr); return JSON.parse(stdout); }; From 9f6cea17aed9b77dc237a04ebbf80d91b2ec6e76 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 19:33:08 +0500 Subject: [PATCH 06/35] chore: add comment for using process.exit() --- packages/cli/src/commands/upgrade/upgrade.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/commands/upgrade/upgrade.ts b/packages/cli/src/commands/upgrade/upgrade.ts index e9b2b9bc1..13129d76f 100644 --- a/packages/cli/src/commands/upgrade/upgrade.ts +++ b/packages/cli/src/commands/upgrade/upgrade.ts @@ -28,7 +28,7 @@ const checkForErrors = (output: string): void => { logger.error( 'Upgrade failed. You do not seem to have an internet connection.', ); - process.exit(); + process.exit(); // exit gracefully so we don't output duplicate error with stack trace } if (hasErrors(output)) { From 1d4b52c4eeafd0bccbb507bf36612ab7b03885ff Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 20:06:54 +0500 Subject: [PATCH 07/35] refactor: improve error outputs in link command --- packages/cli/src/commands/link/link.ts | 2 +- packages/cli/src/commands/link/linkAll.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/link/link.ts b/packages/cli/src/commands/link/link.ts index a23d04340..d1cf9bba7 100644 --- a/packages/cli/src/commands/link/link.ts +++ b/packages/cli/src/commands/link/link.ts @@ -49,7 +49,7 @@ async function link( ); if (rawPackageName === undefined) { - logger.debug('No package name provided, will linking all possible assets.'); + logger.debug('No package name provided, will link all possible assets.'); return linkAll(ctx, {linkDeps: opts.all, linkAssets: true}); } diff --git a/packages/cli/src/commands/link/linkAll.ts b/packages/cli/src/commands/link/linkAll.ts index 48610253a..3ff6f37f5 100644 --- a/packages/cli/src/commands/link/linkAll.ts +++ b/packages/cli/src/commands/link/linkAll.ts @@ -21,7 +21,7 @@ async function linkAll(config: Config, options: Options) { logger.info( `Linking dependencies using "${chalk.bold( 'link', - )}" command is now legacy and likely unnecessary. We encourage you to try ${chalk.bold( + )}" command is now legacy and most likely unnecessary. We encourage you to try ${chalk.bold( 'autolinking', )} that comes with React Native v0.60 default template. Autolinking happens at build time – during CocoaPods install or Gradle install phase. More information: ${chalk.dim.underline( 'https://github.com/react-native-community/cli/blob/master/docs/autolinking.md', From b44a7e82884b8a74a19c44c996b804530e68967e Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sat, 3 Aug 2019 20:07:19 +0500 Subject: [PATCH 08/35] refactor: use for of loop --- packages/cli/src/commands/link/linkAll.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/src/commands/link/linkAll.ts b/packages/cli/src/commands/link/linkAll.ts index 3ff6f37f5..f0bc86bf2 100644 --- a/packages/cli/src/commands/link/linkAll.ts +++ b/packages/cli/src/commands/link/linkAll.ts @@ -28,8 +28,7 @@ async function linkAll(config: Config, options: Options) { )}`, ); - for (let key in config.dependencies) { - const dependency = config.dependencies[key]; + for (const dependency of config.dependencies) { try { if (dependency.hooks.prelink) { await makeHook(dependency.hooks.prelink)(); From c4f1f467108ebc4a31ce77514605c1b35b6a54f3 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sun, 4 Aug 2019 05:43:19 +0500 Subject: [PATCH 09/35] refactor: check package before uninstalling --- .../cli/src/commands/install/uninstall.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/cli/src/commands/install/uninstall.ts b/packages/cli/src/commands/install/uninstall.ts index f5c46bf1b..6822fb233 100644 --- a/packages/cli/src/commands/install/uninstall.ts +++ b/packages/cli/src/commands/install/uninstall.ts @@ -9,10 +9,29 @@ import {Config} from '@react-native-community/cli-types'; import {logger} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import unlink from '../link/unlink'; +import chalk from 'chalk'; async function uninstall(args: Array, ctx: Config): Promise { const name = args[0]; + if (!Object.keys(ctx.dependencies).includes(name)) { + logger.error( + `Unknown package name "${chalk.bgRed.dim( + name, + )}". The package you are trying to uninstall is not present in your "package.json" dependencies.`, + ); + logger.info( + `${chalk.bold( + 'We found the following dependencies installed in your project:\n', + )}${chalk.green.dim( + Object.keys(ctx.dependencies) + .map(dependency => ` - ${dependency}`) + .join('\n'), + )}`, + ); + process.exit(); + } + logger.info(`Unlinking "${name}"...`); await unlink.func([name], ctx, {}); From bc6c63363ccb837043b5ea0265b2c8b759bf2dcd Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sun, 4 Aug 2019 17:48:42 +0500 Subject: [PATCH 10/35] refactor: use CLIError instead of direct exit --- packages/cli/src/commands/upgrade/upgrade.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/commands/upgrade/upgrade.ts b/packages/cli/src/commands/upgrade/upgrade.ts index 13129d76f..858fd6c8f 100644 --- a/packages/cli/src/commands/upgrade/upgrade.ts +++ b/packages/cli/src/commands/upgrade/upgrade.ts @@ -25,15 +25,13 @@ const hasWarnings = (output: string): boolean => output.includes('npm WARN'); const checkForErrors = (output: string): void => { if (!isConnected(output)) { - logger.error( + throw new CLIError( 'Upgrade failed. You do not seem to have an internet connection.', ); - process.exit(); // exit gracefully so we don't output duplicate error with stack trace } if (hasErrors(output)) { - logger.error('Upgrade failed with the following errors:', output); - process.exit(); + throw new CLIError(`Upgrade failed with the following errors:\n${output}`); } if (hasWarnings(output)) { From d6f56572bee45fdde5878292cfa32fbc653d0850 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sun, 4 Aug 2019 18:32:42 +0500 Subject: [PATCH 11/35] refactor: handle potential android pkg name errors --- .../src/commands/runAndroid/index.ts | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index a9fa9db00..62e04fe15 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -28,6 +28,11 @@ function checkAndroid(root: string) { return fs.existsSync(path.join(root, 'android/gradlew')); } +// Validates that the package name is correct +function validatePackageName(packageName: string) { + return /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/.test(packageName); +} + export interface Flags { tasks?: Array; root: string; @@ -125,9 +130,31 @@ function buildAndRun(args: Flags) { // "app" is usually the default value for Android apps with only 1 app const {appFolder} = args; // @ts-ignore - const packageName = fs - .readFileSync(`${appFolder}/src/main/AndroidManifest.xml`, 'utf8') - .match(/package="(.+?)"/)[1]; + const androidManifest = fs.readFileSync( + `${appFolder}/src/main/AndroidManifest.xml`, + 'utf8', + ); + + let packageNameMatchArray = androidManifest.match(/package="(.+?)"/); + if (!packageNameMatchArray || packageNameMatchArray.length <= 0) { + throw new CLIError( + `Failed to build the app: No package name found. Found errors in ${chalk.underline.dim( + `${appFolder}/src/main/AndroidManifest.xml`, + )}`, + ); + } + + let packageName = packageNameMatchArray[1]; + + if (!validatePackageName(packageName)) { + logger.warn( + `Invalid application's package name "${chalk.bgRed( + packageName, + )}" in 'AndroidManifest.xml'. Read guidelines for setting the package name here: ${chalk.underline.dim( + 'https://developer.android.com/studio/build/application-id', + )}`, + ); // we can also directly add the package naming rules here + } const packageNameWithSuffix = getPackageNameWithSuffix( args.appId, From a69ee5b98b62e17ee56f2f522f88dc80c8a9b5e7 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Sun, 4 Aug 2019 18:48:01 +0500 Subject: [PATCH 12/35] refactor: fix typos/mistakes in error outputs --- packages/platform-android/src/commands/runAndroid/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index 62e04fe15..5a07c3b4f 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -207,7 +207,7 @@ function runOnSpecificDevice( ); } } else { - logger.error('No Android devices connected.'); + logger.error('No Android device or emulator connected.'); } } @@ -272,7 +272,7 @@ function getInstallApkName( return apkName; } - throw new Error('Not found the correct install APK file!'); + throw new Error('Could not find the correct install APK file!'); } function installAndLaunchOnDevice( From f32143147ee31516bb4355ba88c2c6768846425b Mon Sep 17 00:00:00 2001 From: thecodrr Date: Mon, 5 Aug 2019 09:11:13 +0500 Subject: [PATCH 13/35] refactor: add adb & android sdk path checks --- .../src/commands/runAndroid/getAdbPath.ts | 49 ++++++++++++++++++- .../src/commands/runAndroid/index.ts | 24 +++++---- packages/tools/src/checkCommandExists.ts | 40 +++++++++++++++ 3 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 packages/tools/src/checkCommandExists.ts diff --git a/packages/platform-android/src/commands/runAndroid/getAdbPath.ts b/packages/platform-android/src/commands/runAndroid/getAdbPath.ts index 0387e16ac..10b465ba6 100644 --- a/packages/platform-android/src/commands/runAndroid/getAdbPath.ts +++ b/packages/platform-android/src/commands/runAndroid/getAdbPath.ts @@ -6,10 +6,57 @@ * */ +import fs from 'fs'; +import {logger, CLIError} from '@react-native-community/cli-tools'; +import chalk from 'chalk'; +import checkCommandExists from './../../../../tools/src/checkCommandExists'; + +function checkAdbPath() { + const adbPath = getAdbPath(); + const adbPathExists = fs.existsSync(adbPath); + const adbCmdExists = checkCommandExists('adb'); + const adbNotFoundError = `"adb" not found in $location$. APK installation $prediction$ fail. Make sure you installed the Android SDK correctly. Read more at ${chalk.underline.dim( + 'https://facebook.github.io/react-native/docs/getting-started', + )}`; + if (!adbPathExists || !adbCmdExists) { + const notFoundLocation = `${ + !adbCmdExists ? 'PATH environment variable' : adbPath + }`; + logger.warn( + adbNotFoundError + .replace('$location$', notFoundLocation) + .replace('$prediction$', 'might'), + ); + } else if (!adbPathExists && !adbCmdExists) { + throw new CLIError( + adbNotFoundError + .replace('$location$', `'PATH environment variable or ${adbPath}`) + .replace('$prediction$', 'will'), + ); + } +} + +function checkAndroidSDKPath() { + const {ANDROID_HOME} = process.env; + if (!ANDROID_HOME || !fs.existsSync(ANDROID_HOME)) { + throw new CLIError( + `Android SDK not found. Make sure you have set ANDROID_HOME environment variable in the system. Read more at ${chalk.underline.dim( + 'https://facebook.github.io/react-native/docs/getting-started#3-configure-the-android_home-environment-variable', + )}`, + ); + } + if (ANDROID_HOME.includes(' ')) { + logger.warn( + `Android SDK path "${ANDROID_HOME}" contains whitespaces which can cause build and install errors. Consider moving the Android SDK to a non-whitespace path.`, + ); + } +} + function getAdbPath() { return process.env.ANDROID_HOME - ? `${process.env.ANDROID_HOME}/platform-tools/adb` + ? `"${process.env.ANDROID_HOME}/platform-tools/adb"` : 'adb'; } export default getAdbPath; +export {checkAndroidSDKPath, checkAdbPath}; diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index 5a07c3b4f..2204ec03c 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -14,7 +14,7 @@ import adb from './adb'; import runOnAllDevices from './runOnAllDevices'; import tryRunAdbReverse from './tryRunAdbReverse'; import tryLaunchAppOnDevice from './tryLaunchAppOnDevice'; -import getAdbPath from './getAdbPath'; +import getAdbPath, {checkAdbPath, checkAndroidSDKPath} from './getAdbPath'; import { isPackagerRunning, logger, @@ -33,6 +33,19 @@ function validatePackageName(packageName: string) { return /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/.test(packageName); } +function performChecks(config: Config, args: Flags) { + if (!checkAndroid(args.root)) { + throw new CLIError( + 'Android project not found. Are you sure this is a React Native project?', + ); + } + checkAndroidSDKPath(); + checkAdbPath(); + + // warn after we have done basic system checks + warnAboutManuallyLinkedLibs(config); +} + export interface Flags { tasks?: Array; root: string; @@ -52,14 +65,7 @@ export interface Flags { * Starts the app on a connected Android emulator or device. */ async function runAndroid(_argv: Array, config: Config, args: Flags) { - if (!checkAndroid(args.root)) { - logger.error( - 'Android project not found. Are you sure this is a React Native project?', - ); - return; - } - - warnAboutManuallyLinkedLibs(config); + performChecks(config, args); if (args.jetifier) { logger.info( diff --git a/packages/tools/src/checkCommandExists.ts b/packages/tools/src/checkCommandExists.ts new file mode 100644 index 000000000..60478c035 --- /dev/null +++ b/packages/tools/src/checkCommandExists.ts @@ -0,0 +1,40 @@ +import {execSync} from 'child_process'; + +function commandExistsUnixSync(commandName: string) { + try { + const stdout = execSync( + `command -v ${commandName} 2>/dev/null` + + ` && { echo >&1 '${commandName} found'; exit 0; }`, + ); + return !!stdout; + } catch (error) { + return false; + } +} + +function commandExistsWindowsSync(commandName: string) { + if (/[\x00-\x1f<>:"\|\?\*]/.test(commandName)) { + return false; + } + try { + const stdout = execSync('where ' + commandName, {stdio: []}); + return !!stdout; + } catch (error) { + return false; + } +} + +function checkCommandExists(commandName: string) { + if (!commandName) return false; + switch (process.platform) { + case 'win32': + return commandExistsWindowsSync(commandName); + case 'darwin': + case 'linux': + return commandExistsUnixSync(commandName); + default: + return false; + } +} + +export default checkCommandExists; From 389e60f7674a89ea238397519294a4db1f71b742 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Mon, 5 Aug 2019 10:05:41 +0500 Subject: [PATCH 14/35] refactor: fix imports --- .../src/commands/runAndroid/getAdbPath.ts | 10 +++++++--- .../platform-android/src/commands/runAndroid/index.ts | 2 +- packages/tools/src/index.ts | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/platform-android/src/commands/runAndroid/getAdbPath.ts b/packages/platform-android/src/commands/runAndroid/getAdbPath.ts index 10b465ba6..7ac3dbe8e 100644 --- a/packages/platform-android/src/commands/runAndroid/getAdbPath.ts +++ b/packages/platform-android/src/commands/runAndroid/getAdbPath.ts @@ -7,9 +7,12 @@ */ import fs from 'fs'; -import {logger, CLIError} from '@react-native-community/cli-tools'; import chalk from 'chalk'; -import checkCommandExists from './../../../../tools/src/checkCommandExists'; +import { + logger, + CLIError, + checkCommandExists, +} from '@react-native-community/cli-tools'; function checkAdbPath() { const adbPath = getAdbPath(); @@ -30,13 +33,14 @@ function checkAdbPath() { } else if (!adbPathExists && !adbCmdExists) { throw new CLIError( adbNotFoundError - .replace('$location$', `'PATH environment variable or ${adbPath}`) + .replace('$location$', `PATH environment variable or ${adbPath}`) .replace('$prediction$', 'will'), ); } } function checkAndroidSDKPath() { + logger.info('here'); const {ANDROID_HOME} = process.env; if (!ANDROID_HOME || !fs.existsSync(ANDROID_HOME)) { throw new CLIError( diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index 2204ec03c..608db106d 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -87,7 +87,7 @@ async function runAndroid(_argv: Array, config: Config, args: Flags) { return buildAndRun(args); } - return isPackagerRunning(args.port).then(result => { + return isPackagerRunning(args.port).then((result: string) => { if (result === 'running') { logger.info('JS server already running.'); } else if (result === 'unrecognized') { diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 0a6f4fafa..5314d79e0 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -3,5 +3,6 @@ export {default as groupFilesByType} from './groupFilesByType'; export {default as isPackagerRunning} from './isPackagerRunning'; export {default as getDefaultUserTerminal} from './getDefaultUserTerminal'; export {default as fetch} from './fetch'; +export {default as checkCommandExists} from './checkCommandExists'; export * from './errors'; From 8a138cec153aab8938586c09df409bd6fa947d54 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Mon, 5 Aug 2019 10:10:14 +0500 Subject: [PATCH 15/35] refactor: improve install apk error outputs --- .../platform-android/src/commands/runAndroid/runOnAllDevices.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/platform-android/src/commands/runAndroid/runOnAllDevices.ts b/packages/platform-android/src/commands/runAndroid/runOnAllDevices.ts index e9779d7ba..8558482f2 100644 --- a/packages/platform-android/src/commands/runAndroid/runOnAllDevices.ts +++ b/packages/platform-android/src/commands/runAndroid/runOnAllDevices.ts @@ -104,7 +104,7 @@ function createInstallError(error: Error & {stderr: string}) { stderr.includes('licences have not been accepted') || stderr.includes('accept the SDK license') ) { - message = `Please accept all necessary SDK licenses using SDK Manager: "${chalk.bold( + message = `Please accept all necessary Android SDK licenses using Android SDK Manager: "${chalk.bold( '$ANDROID_HOME/tools/bin/sdkmanager --licenses', )}"`; } From 207ea95366986215c121c99d972c86ca0326b830 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Mon, 5 Aug 2019 10:16:00 +0500 Subject: [PATCH 16/35] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Michał Pierzchała --- packages/cli/src/commands/bundle/saveAssets.ts | 2 +- packages/cli/src/commands/init/templateName.ts | 12 ++++++------ .../src/commands/runAndroid/index.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/commands/bundle/saveAssets.ts b/packages/cli/src/commands/bundle/saveAssets.ts index 691e8b949..bc7cb422d 100644 --- a/packages/cli/src/commands/bundle/saveAssets.ts +++ b/packages/cli/src/commands/bundle/saveAssets.ts @@ -31,7 +31,7 @@ function saveAssets( } if (!fs.existsSync(assetsDest)) { - let error = `The specified assets destination folder: "${assetsDest}" does not exist, stopping...`; + let error = `The specified assets destination folder "${assetsDest}" does not exist.`; logger.error(error); return Promise.reject(); } diff --git a/packages/cli/src/commands/init/templateName.ts b/packages/cli/src/commands/init/templateName.ts index 7e649cedb..692063f9e 100644 --- a/packages/cli/src/commands/init/templateName.ts +++ b/packages/cli/src/commands/init/templateName.ts @@ -1,6 +1,6 @@ import path from 'path'; import {URL} from 'url'; -import fs from 'fs-extra'; +import fs from 'fs'; const FILE_PROTOCOL = /file:/; const TARBALL = /\.tgz$/; @@ -15,19 +15,19 @@ function handleFileProtocol(filePath: string) { } if (!fs.existsSync(uri)) { throw new Error( - `Failed to retrieve package name. The specified template directory path: ${uri} does not exist or is invalid.`, + `Failed to retrieve package name. The specified template directory path "${uri}" does not exist or is invalid.`, ); } const packageJsonPath = path.join(uri, 'package.json'); if (!fs.existsSync(packageJsonPath)) { throw new Error( - 'Failed to retrieve package name. We expect the template directory to include package.json file, but no such file was found.', + 'Failed to retrieve package name. We expect the template directory to include "package.json" file, but it was not found.', ); } const packageJson = require(packageJsonPath); if (!packageJson.name) { throw new Error( - `Failed to retrieve package name. We expect the package.json to include package name, e.g.: "template-name", but received: "${JSON.stringify( + `Failed to retrieve template name. We expect the "package.json" of the template to include the "name" property, but we found "${packageJson.name}" which is invalid.` packageJson, )}"`, ); @@ -40,8 +40,8 @@ function handleFileProtocol(filePath: string) { function handleTarball(filePath: string) { if (!fs.existsSync(filePath)) { - throw new Error( - `Failed to retrieve tarball name. The specified tarball path: ${filePath} does not exist or is invalid.`, + throw new CLIError( + `Failed to retrieve tarball name. The specified tarball path "${filePath}" does not exist or is invalid.`, ); } const nameWithVersion = path.parse(path.basename(filePath)).name; diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index 608db106d..adb75212e 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -278,7 +278,7 @@ function getInstallApkName( return apkName; } - throw new Error('Could not find the correct install APK file!'); + throw new CLIError('Could not find the correct install APK file.'); } function installAndLaunchOnDevice( From 6bf9dba67c95f083d647c12148b74d55dba34c16 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Mon, 5 Aug 2019 10:21:57 +0500 Subject: [PATCH 17/35] refactor: add init doc link in error output --- packages/cli/src/commands/bundle/saveAssets.ts | 5 ++--- packages/cli/src/commands/init/template.ts | 7 +++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/commands/bundle/saveAssets.ts b/packages/cli/src/commands/bundle/saveAssets.ts index bc7cb422d..0540c4458 100644 --- a/packages/cli/src/commands/bundle/saveAssets.ts +++ b/packages/cli/src/commands/bundle/saveAssets.ts @@ -13,7 +13,7 @@ import fs from 'fs'; import filterPlatformAssetScales from './filterPlatformAssetScales'; import getAssetDestPathAndroid from './getAssetDestPathAndroid'; import getAssetDestPathIOS from './getAssetDestPathIOS'; -import {logger} from '@react-native-community/cli-tools'; +import {logger, CLIError} from '@react-native-community/cli-tools'; import {AssetData} from './buildBundle'; interface CopiedFiles { @@ -32,8 +32,7 @@ function saveAssets( if (!fs.existsSync(assetsDest)) { let error = `The specified assets destination folder "${assetsDest}" does not exist.`; - logger.error(error); - return Promise.reject(); + throw new CLIError(error); } const getAssetDestPath = diff --git a/packages/cli/src/commands/init/template.ts b/packages/cli/src/commands/init/template.ts index a7640a516..8c6b10518 100644 --- a/packages/cli/src/commands/init/template.ts +++ b/packages/cli/src/commands/init/template.ts @@ -4,7 +4,8 @@ import {logger} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import copyFiles from '../../tools/copyFiles'; import replacePathSepForRegex from '../../tools/replacePathSepForRegex'; -import fs from 'fs-extra'; +import fs from 'fs'; +import chalk from 'chalk'; export type TemplateConfig = { placeholderName: string; @@ -40,7 +41,9 @@ export function getTemplateConfig( logger.debug(`Getting config from ${configFilePath}.js`); if (!fs.existsSync(configFilePath)) { throw new Error( - `Invalid template '${templateName}' specified. Make sure the template is CLI v2 compliant i.e. has a 'template.config.js' file.`, + `Invalid template '${templateName}' specified. Make sure the template is CLI v2 compliant: ${chalk.underline.dim( + 'https://github.com/react-native-community/cli/blob/master/docs/init.md#creating-custom-template', + )}`, ); } return require(configFilePath); From 168d67936e78bcb85ed8cb521ada7dac9b066e9e Mon Sep 17 00:00:00 2001 From: thecodrr Date: Mon, 5 Aug 2019 18:33:13 +0500 Subject: [PATCH 18/35] test: make sure all tests pass --- __e2e__/init.test.ts | 1 + __e2e__/uninstall.test.ts | 5 ++-- .../commands/init/__tests__/template.test.ts | 7 +++--- .../init/__tests__/templateName.test.ts | 20 ++++++--------- packages/cli/src/commands/init/template.ts | 6 ++--- .../cli/src/commands/init/templateName.ts | 25 +++++++++++-------- packages/cli/src/commands/upgrade/upgrade.ts | 1 + 7 files changed, 33 insertions(+), 32 deletions(-) diff --git a/__e2e__/init.test.ts b/__e2e__/init.test.ts index 518b22c71..f2dee08cb 100644 --- a/__e2e__/init.test.ts +++ b/__e2e__/init.test.ts @@ -47,6 +47,7 @@ test('init --template', () => { '--template', 'react-native-new-template', 'TestInit', + '--verbose', ]); expect(stdout).toContain('Welcome to React Native!'); diff --git a/__e2e__/uninstall.test.ts b/__e2e__/uninstall.test.ts index 748d46f5e..4d9e84968 100644 --- a/__e2e__/uninstall.test.ts +++ b/__e2e__/uninstall.test.ts @@ -35,10 +35,9 @@ test('uninstall fails when package is not installed', () => { "dependencies": {} }`, }); - const {stderr, code} = run(DIR, ['uninstall', pkg], {expectedFailure: true}); + const {stderr} = run(DIR, ['uninstall', pkg], {expectedFailure: true}); - expect(stderr).toContain(`Failed to unlink "${pkg}".`); - expect(code).toBe(1); + expect(stderr).toContain(`error Unknown package name "${pkg}".`); }); test.each(['yarn', 'npm'])('uninstall module with %s', pm => { diff --git a/packages/cli/src/commands/init/__tests__/template.test.ts b/packages/cli/src/commands/init/__tests__/template.test.ts index a727d44aa..2377fb09e 100644 --- a/packages/cli/src/commands/init/__tests__/template.test.ts +++ b/packages/cli/src/commands/init/__tests__/template.test.ts @@ -1,6 +1,7 @@ jest.mock('execa', () => jest.fn()); import execa from 'execa'; import path from 'path'; +import fs from 'fs'; import * as PackageManger from '../../../tools/packageManager'; import { installTemplatePackage, @@ -32,7 +33,7 @@ test('installTemplatePackage', async () => { test('getTemplateConfig', () => { jest.mock( - `${TEMPLATE_SOURCE_DIR}/node_modules/${TEMPLATE_NAME}/template.config`, + `${TEMPLATE_SOURCE_DIR}/node_modules/${TEMPLATE_NAME}/template.config.js`, () => ({ placeholderName: 'someName', templateDir: 'someDir', @@ -42,7 +43,7 @@ test('getTemplateConfig', () => { }, ); jest.spyOn(path, 'resolve').mockImplementationOnce((...e) => e.join('/')); - + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); expect(getTemplateConfig(TEMPLATE_NAME, TEMPLATE_SOURCE_DIR)).toEqual({ placeholderName: 'someName', templateDir: 'someDir', @@ -51,7 +52,7 @@ test('getTemplateConfig', () => { TEMPLATE_SOURCE_DIR, 'node_modules', TEMPLATE_NAME, - 'template.config', + 'template.config.js', ); }); diff --git a/packages/cli/src/commands/init/__tests__/templateName.test.ts b/packages/cli/src/commands/init/__tests__/templateName.test.ts index 87dfcd261..b109107c1 100644 --- a/packages/cli/src/commands/init/__tests__/templateName.test.ts +++ b/packages/cli/src/commands/init/__tests__/templateName.test.ts @@ -1,22 +1,17 @@ import {processTemplateName} from '../templateName'; +import fs from 'fs'; const RN_NPM_PACKAGE = 'react-native'; const ABS_RN_PATH = '/path/to/react-native'; +const ABS_RN_PATH_WINDOWS = 'path/to/react-native'; test('supports file protocol with absolute path', async () => { - if (process.platform === 'win32') { - console.warn('[SKIP] Jest virtual mocks seem to be broken on Windows'); - return; - } - jest.mock( - `${ABS_RN_PATH}/package.json`, - () => ({ - name: 'react-native', - }), - {virtual: true}, - ); + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + jest + .spyOn(fs, 'readFileSync') + .mockImplementation(() => JSON.stringify({name: 'react-native'})); expect(await processTemplateName(`file://${ABS_RN_PATH}`)).toEqual({ - uri: ABS_RN_PATH, + uri: process.platform === 'win32' ? ABS_RN_PATH_WINDOWS : ABS_RN_PATH, name: RN_NPM_PACKAGE, }); }); @@ -45,6 +40,7 @@ test.each` test('supports path to tgz archives', async () => { const ABS_RN_TARBALL_PATH = '/path/to/react-native/react-native-1.2.3-rc.0.tgz'; + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); expect(await processTemplateName(`file://${ABS_RN_TARBALL_PATH}`)).toEqual({ uri: `file://${ABS_RN_TARBALL_PATH}`, name: 'react-native', diff --git a/packages/cli/src/commands/init/template.ts b/packages/cli/src/commands/init/template.ts index 8c6b10518..eecd19a1b 100644 --- a/packages/cli/src/commands/init/template.ts +++ b/packages/cli/src/commands/init/template.ts @@ -1,6 +1,6 @@ import execa from 'execa'; import path from 'path'; -import {logger} from '@react-native-community/cli-tools'; +import {logger, CLIError} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import copyFiles from '../../tools/copyFiles'; import replacePathSepForRegex from '../../tools/replacePathSepForRegex'; @@ -35,12 +35,12 @@ export function getTemplateConfig( templateSourceDir, 'node_modules', templateName, - 'template.config', + 'template.config.js', ); logger.debug(`Getting config from ${configFilePath}.js`); if (!fs.existsSync(configFilePath)) { - throw new Error( + throw new CLIError( `Invalid template '${templateName}' specified. Make sure the template is CLI v2 compliant: ${chalk.underline.dim( 'https://github.com/react-native-community/cli/blob/master/docs/init.md#creating-custom-template', )}`, diff --git a/packages/cli/src/commands/init/templateName.ts b/packages/cli/src/commands/init/templateName.ts index 692063f9e..942b0ca8f 100644 --- a/packages/cli/src/commands/init/templateName.ts +++ b/packages/cli/src/commands/init/templateName.ts @@ -1,6 +1,7 @@ import path from 'path'; import {URL} from 'url'; import fs from 'fs'; +import {CLIError} from '@react-native-community/cli-tools'; const FILE_PROTOCOL = /file:/; const TARBALL = /\.tgz$/; @@ -10,26 +11,28 @@ const VERSIONED_PACKAGE = /(@?.+)(@)(.+)/; function handleFileProtocol(filePath: string) { let uri = new URL(filePath).pathname; if (process.platform === 'win32') { - // On Windows, the pathname has an extra leading / so remove that + // On Windows, the pathname has an extra / at the start, so remove that uri = uri.substring(1); } if (!fs.existsSync(uri)) { - throw new Error( + throw new CLIError( `Failed to retrieve package name. The specified template directory path "${uri}" does not exist or is invalid.`, ); } const packageJsonPath = path.join(uri, 'package.json'); if (!fs.existsSync(packageJsonPath)) { - throw new Error( + throw new CLIError( 'Failed to retrieve package name. We expect the template directory to include "package.json" file, but it was not found.', ); } - const packageJson = require(packageJsonPath); + const packageJson = JSON.parse( + fs.readFileSync(packageJsonPath, {encoding: 'utf8'}), + ); if (!packageJson.name) { - throw new Error( - `Failed to retrieve template name. We expect the "package.json" of the template to include the "name" property, but we found "${packageJson.name}" which is invalid.` - packageJson, - )}"`, + throw new CLIError( + `Failed to retrieve template name. We expect the "package.json" of the template to include the "name" property, but we found "${ + packageJson.name + }" which is invalid.`, ); } return { @@ -47,7 +50,7 @@ function handleTarball(filePath: string) { const nameWithVersion = path.parse(path.basename(filePath)).name; const tarballVersionMatch = nameWithVersion.match(VERSION_POSTFIX); if (!tarballVersionMatch) { - throw new Error( + throw new CLIError( `Failed to retrieve tarball name. We expect the tarball to include package name and version, e.g.: "template-name-1.2.3-rc.0.tgz", but received: "${nameWithVersion}".`, ); } @@ -61,7 +64,7 @@ function handleTarball(filePath: string) { function handleVersionedPackage(versionedPackage: string) { const versionedPackageMatch = versionedPackage.match(VERSIONED_PACKAGE); if (!versionedPackageMatch) { - throw new Error( + throw new CLIError( `Failed to retrieve package name. We expect the package to include name and version, e.g.: "template-name@1.2.3-rc.0", but received: "${versionedPackage}".`, ); } @@ -71,7 +74,7 @@ function handleVersionedPackage(versionedPackage: string) { }; } -export async function processTemplateName(templateName: string) { +export function processTemplateName(templateName: string) { if (templateName.match(TARBALL)) { return handleTarball(templateName); } diff --git a/packages/cli/src/commands/upgrade/upgrade.ts b/packages/cli/src/commands/upgrade/upgrade.ts index 858fd6c8f..ba7b8d561 100644 --- a/packages/cli/src/commands/upgrade/upgrade.ts +++ b/packages/cli/src/commands/upgrade/upgrade.ts @@ -24,6 +24,7 @@ const hasErrors = (output: string): boolean => output.includes('npm ERR'); const hasWarnings = (output: string): boolean => output.includes('npm WARN'); const checkForErrors = (output: string): void => { + if (!output) return; if (!isConnected(output)) { throw new CLIError( 'Upgrade failed. You do not seem to have an internet connection.', From d851843cfa8c4836c66503b97df72534914e00b1 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Tue, 6 Aug 2019 08:37:47 +0500 Subject: [PATCH 19/35] refactor: use try/catch around readFileSync --- packages/cli/src/commands/init/templateName.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/commands/init/templateName.ts b/packages/cli/src/commands/init/templateName.ts index 942b0ca8f..ead9dc74a 100644 --- a/packages/cli/src/commands/init/templateName.ts +++ b/packages/cli/src/commands/init/templateName.ts @@ -16,18 +16,21 @@ function handleFileProtocol(filePath: string) { } if (!fs.existsSync(uri)) { throw new CLIError( - `Failed to retrieve package name. The specified template directory path "${uri}" does not exist or is invalid.`, + `Failed to retrieve template name. The specified template directory path "${uri}" does not exist or is invalid.`, ); } const packageJsonPath = path.join(uri, 'package.json'); - if (!fs.existsSync(packageJsonPath)) { + + try { + const packageJson = JSON.parse( + fs.readFileSync(packageJsonPath, {encoding: 'utf8'}), + ); + } catch { throw new CLIError( - 'Failed to retrieve package name. We expect the template directory to include "package.json" file, but it was not found.', + 'Failed to retrieve template name. We expect the template directory to include "package.json" file, but it was not found.', ); } - const packageJson = JSON.parse( - fs.readFileSync(packageJsonPath, {encoding: 'utf8'}), - ); + if (!packageJson.name) { throw new CLIError( `Failed to retrieve template name. We expect the "package.json" of the template to include the "name" property, but we found "${ From c0a2cac0f8ce46a0a452af7bed1f41922430895b Mon Sep 17 00:00:00 2001 From: thecodrr Date: Tue, 6 Aug 2019 08:50:10 +0500 Subject: [PATCH 20/35] refactor: do not read build.gradle twice --- packages/platform-android/src/link/isInstalled.ts | 4 ++-- .../src/link/patches/makeBuildPatch.ts | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/platform-android/src/link/isInstalled.ts b/packages/platform-android/src/link/isInstalled.ts index de53851e1..fbea79f7d 100644 --- a/packages/platform-android/src/link/isInstalled.ts +++ b/packages/platform-android/src/link/isInstalled.ts @@ -7,12 +7,12 @@ */ import fs from 'fs'; -import makeBuildPatch from './patches/makeBuildPatch'; +import {makeInstallPattern} from './patches/makeBuildPatch'; export default function isInstalled( config: {buildGradlePath: string}, name: string, ) { const buildGradle = fs.readFileSync(config.buildGradlePath, 'utf8'); - return makeBuildPatch(name).installPattern.test(buildGradle); + return makeInstallPattern(name).test(buildGradle); } diff --git a/packages/platform-android/src/link/patches/makeBuildPatch.ts b/packages/platform-android/src/link/patches/makeBuildPatch.ts index 74d8392be..b73360135 100644 --- a/packages/platform-android/src/link/patches/makeBuildPatch.ts +++ b/packages/platform-android/src/link/patches/makeBuildPatch.ts @@ -13,17 +13,18 @@ const depConfigs = ['compile', 'api', 'implementation']; export default function makeBuildPatch(name: string, buildGradlePath?: string) { const normalizedProjectName = normalizeProjectName(name); - const installPattern = new RegExp( - buildDepRegExp(normalizedProjectName, ...depConfigs), - ); - return { - installPattern, + installPattern: makeInstallPattern(name), pattern: /[^ \t]dependencies {(\r\n|\n)/, patch: makePatchString(normalizedProjectName, buildGradlePath), }; } +export function makeInstallPattern(name: string) { + const normalizedProjectName = normalizeProjectName(name); + return new RegExp(buildDepRegExp(normalizedProjectName, ...depConfigs)); +} + function makePatchString( normalizedProjectName: string, buildGradlePath?: string, From d073a04c8bc311ff74ab28244c270ac0e8111c37 Mon Sep 17 00:00:00 2001 From: thecodrr Date: Tue, 6 Aug 2019 09:13:29 +0500 Subject: [PATCH 21/35] refactor: clean up code in android linking --- packages/platform-android/src/link/registerNativeModule.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/platform-android/src/link/registerNativeModule.ts b/packages/platform-android/src/link/registerNativeModule.ts index e02a03583..648bfd3c1 100644 --- a/packages/platform-android/src/link/registerNativeModule.ts +++ b/packages/platform-android/src/link/registerNativeModule.ts @@ -24,14 +24,12 @@ export default function registerNativeAndroidModule( params: AndroidProjectParams, projectConfig: AndroidProjectConfig, ) { - const buildPatch = makeBuildPatch(name); - applyPatch( projectConfig.settingsGradlePath, makeSettingsPatch(name, androidConfig, projectConfig), ); - applyPatch(projectConfig.buildGradlePath, buildPatch); + applyPatch(projectConfig.buildGradlePath, makeBuildPatch(name)); applyPatch(projectConfig.stringsPath, makeStringsPatch(params, name)); applyPatch( From 9087af4d403390a7de9334829f8d6b66b790a5ca Mon Sep 17 00:00:00 2001 From: thecodrr Date: Tue, 6 Aug 2019 09:37:17 +0500 Subject: [PATCH 22/35] fix: packageJson not defined in templateName --- packages/cli/src/commands/init/templateName.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/commands/init/templateName.ts b/packages/cli/src/commands/init/templateName.ts index ead9dc74a..90d79f8cb 100644 --- a/packages/cli/src/commands/init/templateName.ts +++ b/packages/cli/src/commands/init/templateName.ts @@ -20,9 +20,9 @@ function handleFileProtocol(filePath: string) { ); } const packageJsonPath = path.join(uri, 'package.json'); - + let packageJson = undefined; try { - const packageJson = JSON.parse( + packageJson = JSON.parse( fs.readFileSync(packageJsonPath, {encoding: 'utf8'}), ); } catch { @@ -31,10 +31,10 @@ function handleFileProtocol(filePath: string) { ); } - if (!packageJson.name) { + if (!packageJson || !packageJson.name) { throw new CLIError( `Failed to retrieve template name. We expect the "package.json" of the template to include the "name" property, but we found "${ - packageJson.name + packageJson ? packageJson.name : `undefined` }" which is invalid.`, ); } From fbf5bd800ec5c6bebddd27da331d40f71c697c3c Mon Sep 17 00:00:00 2001 From: thecodrr Date: Tue, 6 Aug 2019 09:39:23 +0500 Subject: [PATCH 23/35] refactor: remove unintentional --verbose flag --- __e2e__/init.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/__e2e__/init.test.ts b/__e2e__/init.test.ts index f2dee08cb..518b22c71 100644 --- a/__e2e__/init.test.ts +++ b/__e2e__/init.test.ts @@ -47,7 +47,6 @@ test('init --template', () => { '--template', 'react-native-new-template', 'TestInit', - '--verbose', ]); expect(stdout).toContain('Welcome to React Native!'); From af2b0cc457ce2b011ad138f3a5450b9aeff1057f Mon Sep 17 00:00:00 2001 From: thecodrr Date: Tue, 6 Aug 2019 09:50:48 +0500 Subject: [PATCH 24/35] refactor: make flow very happy --- packages/cli/src/commands/bundle/assetPathUtils.ts | 2 +- packages/cli/src/commands/link/linkAll.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/bundle/assetPathUtils.ts b/packages/cli/src/commands/bundle/assetPathUtils.ts index 7e7676715..c7e5f4472 100644 --- a/packages/cli/src/commands/bundle/assetPathUtils.ts +++ b/packages/cli/src/commands/bundle/assetPathUtils.ts @@ -31,7 +31,7 @@ function getAndroidAssetSuffix(scale: number): string { case 4: return 'xxxhdpi'; default: - return undefined; + return ''; } } diff --git a/packages/cli/src/commands/link/linkAll.ts b/packages/cli/src/commands/link/linkAll.ts index f0bc86bf2..3ff6f37f5 100644 --- a/packages/cli/src/commands/link/linkAll.ts +++ b/packages/cli/src/commands/link/linkAll.ts @@ -28,7 +28,8 @@ async function linkAll(config: Config, options: Options) { )}`, ); - for (const dependency of config.dependencies) { + for (let key in config.dependencies) { + const dependency = config.dependencies[key]; try { if (dependency.hooks.prelink) { await makeHook(dependency.hooks.prelink)(); From f2f6e084b36ad2aaffaaa2e3055c3d6eee77750b Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Fri, 23 Aug 2019 10:30:29 +0500 Subject: [PATCH 25/35] refactor: remove unnecessary variable definition --- packages/cli/src/commands/bundle/saveAssets.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/src/commands/bundle/saveAssets.ts b/packages/cli/src/commands/bundle/saveAssets.ts index 0540c4458..c572df3cb 100644 --- a/packages/cli/src/commands/bundle/saveAssets.ts +++ b/packages/cli/src/commands/bundle/saveAssets.ts @@ -31,8 +31,7 @@ function saveAssets( } if (!fs.existsSync(assetsDest)) { - let error = `The specified assets destination folder "${assetsDest}" does not exist.`; - throw new CLIError(error); + throw new CLIError(`The specified assets destination folder "${assetsDest}" does not exist.`); } const getAssetDestPath = From 415bb2596f159744a72e7fbe712707a45bf61250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Fri, 11 Oct 2019 16:06:34 +0200 Subject: [PATCH 26/35] pkgjson undefined tweak --- packages/cli/src/commands/init/templateName.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/init/templateName.ts b/packages/cli/src/commands/init/templateName.ts index 90d79f8cb..f4c9b67fb 100644 --- a/packages/cli/src/commands/init/templateName.ts +++ b/packages/cli/src/commands/init/templateName.ts @@ -20,7 +20,7 @@ function handleFileProtocol(filePath: string) { ); } const packageJsonPath = path.join(uri, 'package.json'); - let packageJson = undefined; + let packageJson; try { packageJson = JSON.parse( fs.readFileSync(packageJsonPath, {encoding: 'utf8'}), @@ -34,7 +34,7 @@ function handleFileProtocol(filePath: string) { if (!packageJson || !packageJson.name) { throw new CLIError( `Failed to retrieve template name. We expect the "package.json" of the template to include the "name" property, but we found "${ - packageJson ? packageJson.name : `undefined` + packageJson ? packageJson.name : 'undefined' }" which is invalid.`, ); } From 879f9b82908b5b4c3685b3d36a46a91efd08c08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 16:49:48 +0100 Subject: [PATCH 27/35] eslint fix --- packages/cli/src/commands/bundle/saveAssets.ts | 4 +++- packages/cli/src/commands/upgrade/upgrade.ts | 4 +++- packages/tools/src/checkCommandExists.ts | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/commands/bundle/saveAssets.ts b/packages/cli/src/commands/bundle/saveAssets.ts index c572df3cb..d563062a9 100644 --- a/packages/cli/src/commands/bundle/saveAssets.ts +++ b/packages/cli/src/commands/bundle/saveAssets.ts @@ -31,7 +31,9 @@ function saveAssets( } if (!fs.existsSync(assetsDest)) { - throw new CLIError(`The specified assets destination folder "${assetsDest}" does not exist.`); + throw new CLIError( + `The specified assets destination folder "${assetsDest}" does not exist.`, + ); } const getAssetDestPath = diff --git a/packages/cli/src/commands/upgrade/upgrade.ts b/packages/cli/src/commands/upgrade/upgrade.ts index ba7b8d561..ed66824b1 100644 --- a/packages/cli/src/commands/upgrade/upgrade.ts +++ b/packages/cli/src/commands/upgrade/upgrade.ts @@ -24,7 +24,9 @@ const hasErrors = (output: string): boolean => output.includes('npm ERR'); const hasWarnings = (output: string): boolean => output.includes('npm WARN'); const checkForErrors = (output: string): void => { - if (!output) return; + if (!output) { + return; + } if (!isConnected(output)) { throw new CLIError( 'Upgrade failed. You do not seem to have an internet connection.', diff --git a/packages/tools/src/checkCommandExists.ts b/packages/tools/src/checkCommandExists.ts index 60478c035..2ae83605a 100644 --- a/packages/tools/src/checkCommandExists.ts +++ b/packages/tools/src/checkCommandExists.ts @@ -25,7 +25,9 @@ function commandExistsWindowsSync(commandName: string) { } function checkCommandExists(commandName: string) { - if (!commandName) return false; + if (!commandName) { + return false; + } switch (process.platform) { case 'win32': return commandExistsWindowsSync(commandName); From e87dc751f1e70dfbe8f484eace4d5a90eeeaebe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 17:21:39 +0100 Subject: [PATCH 28/35] remove adb/android_home checks because we have doctor --- .../cli/src/commands/install/uninstall.ts | 13 +++-- .../src/commands/runAndroid/getAdbPath.ts | 53 +------------------ .../src/commands/runAndroid/index.ts | 4 +- 3 files changed, 8 insertions(+), 62 deletions(-) diff --git a/packages/cli/src/commands/install/uninstall.ts b/packages/cli/src/commands/install/uninstall.ts index 6822fb233..139cb189b 100644 --- a/packages/cli/src/commands/install/uninstall.ts +++ b/packages/cli/src/commands/install/uninstall.ts @@ -6,7 +6,7 @@ * */ import {Config} from '@react-native-community/cli-types'; -import {logger} from '@react-native-community/cli-tools'; +import {logger, CLIError} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import unlink from '../link/unlink'; import chalk from 'chalk'; @@ -15,11 +15,6 @@ async function uninstall(args: Array, ctx: Config): Promise { const name = args[0]; if (!Object.keys(ctx.dependencies).includes(name)) { - logger.error( - `Unknown package name "${chalk.bgRed.dim( - name, - )}". The package you are trying to uninstall is not present in your "package.json" dependencies.`, - ); logger.info( `${chalk.bold( 'We found the following dependencies installed in your project:\n', @@ -29,7 +24,11 @@ async function uninstall(args: Array, ctx: Config): Promise { .join('\n'), )}`, ); - process.exit(); + throw new CLIError( + `Unknown package name "${chalk.bgRed.dim( + name, + )}". The package you are trying to uninstall is not present in your "package.json" dependencies.`, + ); } logger.info(`Unlinking "${name}"...`); diff --git a/packages/platform-android/src/commands/runAndroid/getAdbPath.ts b/packages/platform-android/src/commands/runAndroid/getAdbPath.ts index 7ac3dbe8e..0387e16ac 100644 --- a/packages/platform-android/src/commands/runAndroid/getAdbPath.ts +++ b/packages/platform-android/src/commands/runAndroid/getAdbPath.ts @@ -6,61 +6,10 @@ * */ -import fs from 'fs'; -import chalk from 'chalk'; -import { - logger, - CLIError, - checkCommandExists, -} from '@react-native-community/cli-tools'; - -function checkAdbPath() { - const adbPath = getAdbPath(); - const adbPathExists = fs.existsSync(adbPath); - const adbCmdExists = checkCommandExists('adb'); - const adbNotFoundError = `"adb" not found in $location$. APK installation $prediction$ fail. Make sure you installed the Android SDK correctly. Read more at ${chalk.underline.dim( - 'https://facebook.github.io/react-native/docs/getting-started', - )}`; - if (!adbPathExists || !adbCmdExists) { - const notFoundLocation = `${ - !adbCmdExists ? 'PATH environment variable' : adbPath - }`; - logger.warn( - adbNotFoundError - .replace('$location$', notFoundLocation) - .replace('$prediction$', 'might'), - ); - } else if (!adbPathExists && !adbCmdExists) { - throw new CLIError( - adbNotFoundError - .replace('$location$', `PATH environment variable or ${adbPath}`) - .replace('$prediction$', 'will'), - ); - } -} - -function checkAndroidSDKPath() { - logger.info('here'); - const {ANDROID_HOME} = process.env; - if (!ANDROID_HOME || !fs.existsSync(ANDROID_HOME)) { - throw new CLIError( - `Android SDK not found. Make sure you have set ANDROID_HOME environment variable in the system. Read more at ${chalk.underline.dim( - 'https://facebook.github.io/react-native/docs/getting-started#3-configure-the-android_home-environment-variable', - )}`, - ); - } - if (ANDROID_HOME.includes(' ')) { - logger.warn( - `Android SDK path "${ANDROID_HOME}" contains whitespaces which can cause build and install errors. Consider moving the Android SDK to a non-whitespace path.`, - ); - } -} - function getAdbPath() { return process.env.ANDROID_HOME - ? `"${process.env.ANDROID_HOME}/platform-tools/adb"` + ? `${process.env.ANDROID_HOME}/platform-tools/adb` : 'adb'; } export default getAdbPath; -export {checkAndroidSDKPath, checkAdbPath}; diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index adb75212e..a90fdf25c 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -14,7 +14,7 @@ import adb from './adb'; import runOnAllDevices from './runOnAllDevices'; import tryRunAdbReverse from './tryRunAdbReverse'; import tryLaunchAppOnDevice from './tryLaunchAppOnDevice'; -import getAdbPath, {checkAdbPath, checkAndroidSDKPath} from './getAdbPath'; +import getAdbPath from './getAdbPath'; import { isPackagerRunning, logger, @@ -39,8 +39,6 @@ function performChecks(config: Config, args: Flags) { 'Android project not found. Are you sure this is a React Native project?', ); } - checkAndroidSDKPath(); - checkAdbPath(); // warn after we have done basic system checks warnAboutManuallyLinkedLibs(config); From 1e4ccb1bf450de38acbca3b36e999a9bb86252b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 17:25:10 +0100 Subject: [PATCH 29/35] use mockImplementationOnce --- packages/cli/src/commands/init/__tests__/template.test.ts | 2 +- packages/cli/src/commands/init/__tests__/templateName.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/commands/init/__tests__/template.test.ts b/packages/cli/src/commands/init/__tests__/template.test.ts index 2377fb09e..cf3c9fedb 100644 --- a/packages/cli/src/commands/init/__tests__/template.test.ts +++ b/packages/cli/src/commands/init/__tests__/template.test.ts @@ -43,7 +43,7 @@ test('getTemplateConfig', () => { }, ); jest.spyOn(path, 'resolve').mockImplementationOnce((...e) => e.join('/')); - jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => true); expect(getTemplateConfig(TEMPLATE_NAME, TEMPLATE_SOURCE_DIR)).toEqual({ placeholderName: 'someName', templateDir: 'someDir', diff --git a/packages/cli/src/commands/init/__tests__/templateName.test.ts b/packages/cli/src/commands/init/__tests__/templateName.test.ts index b109107c1..51e515683 100644 --- a/packages/cli/src/commands/init/__tests__/templateName.test.ts +++ b/packages/cli/src/commands/init/__tests__/templateName.test.ts @@ -6,10 +6,10 @@ const ABS_RN_PATH = '/path/to/react-native'; const ABS_RN_PATH_WINDOWS = 'path/to/react-native'; test('supports file protocol with absolute path', async () => { - jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => true); jest .spyOn(fs, 'readFileSync') - .mockImplementation(() => JSON.stringify({name: 'react-native'})); + .mockImplementationOnce(() => JSON.stringify({name: 'react-native'})); expect(await processTemplateName(`file://${ABS_RN_PATH}`)).toEqual({ uri: process.platform === 'win32' ? ABS_RN_PATH_WINDOWS : ABS_RN_PATH, name: RN_NPM_PACKAGE, From a3b88f4f7193a5e3d5879aeef3f0cc3df150ac5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 17:31:49 +0100 Subject: [PATCH 30/35] revert link changes, as it's going to be removed in next version --- packages/platform-android/src/link/isInstalled.ts | 4 ++-- .../src/link/patches/makeBuildPatch.ts | 11 +++++------ .../platform-android/src/link/registerNativeModule.ts | 4 +++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/platform-android/src/link/isInstalled.ts b/packages/platform-android/src/link/isInstalled.ts index fbea79f7d..de53851e1 100644 --- a/packages/platform-android/src/link/isInstalled.ts +++ b/packages/platform-android/src/link/isInstalled.ts @@ -7,12 +7,12 @@ */ import fs from 'fs'; -import {makeInstallPattern} from './patches/makeBuildPatch'; +import makeBuildPatch from './patches/makeBuildPatch'; export default function isInstalled( config: {buildGradlePath: string}, name: string, ) { const buildGradle = fs.readFileSync(config.buildGradlePath, 'utf8'); - return makeInstallPattern(name).test(buildGradle); + return makeBuildPatch(name).installPattern.test(buildGradle); } diff --git a/packages/platform-android/src/link/patches/makeBuildPatch.ts b/packages/platform-android/src/link/patches/makeBuildPatch.ts index b73360135..74d8392be 100644 --- a/packages/platform-android/src/link/patches/makeBuildPatch.ts +++ b/packages/platform-android/src/link/patches/makeBuildPatch.ts @@ -13,18 +13,17 @@ const depConfigs = ['compile', 'api', 'implementation']; export default function makeBuildPatch(name: string, buildGradlePath?: string) { const normalizedProjectName = normalizeProjectName(name); + const installPattern = new RegExp( + buildDepRegExp(normalizedProjectName, ...depConfigs), + ); + return { - installPattern: makeInstallPattern(name), + installPattern, pattern: /[^ \t]dependencies {(\r\n|\n)/, patch: makePatchString(normalizedProjectName, buildGradlePath), }; } -export function makeInstallPattern(name: string) { - const normalizedProjectName = normalizeProjectName(name); - return new RegExp(buildDepRegExp(normalizedProjectName, ...depConfigs)); -} - function makePatchString( normalizedProjectName: string, buildGradlePath?: string, diff --git a/packages/platform-android/src/link/registerNativeModule.ts b/packages/platform-android/src/link/registerNativeModule.ts index 648bfd3c1..e02a03583 100644 --- a/packages/platform-android/src/link/registerNativeModule.ts +++ b/packages/platform-android/src/link/registerNativeModule.ts @@ -24,12 +24,14 @@ export default function registerNativeAndroidModule( params: AndroidProjectParams, projectConfig: AndroidProjectConfig, ) { + const buildPatch = makeBuildPatch(name); + applyPatch( projectConfig.settingsGradlePath, makeSettingsPatch(name, androidConfig, projectConfig), ); - applyPatch(projectConfig.buildGradlePath, makeBuildPatch(name)); + applyPatch(projectConfig.buildGradlePath, buildPatch); applyPatch(projectConfig.stringsPath, makeStringsPatch(params, name)); applyPatch( From 3091c130198d848a5fdf61199b0827aeaa2c1819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 17:35:35 +0100 Subject: [PATCH 31/35] inline fns --- packages/cli/src/commands/upgrade/upgrade.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/commands/upgrade/upgrade.ts b/packages/cli/src/commands/upgrade/upgrade.ts index ed66824b1..28faad31f 100644 --- a/packages/cli/src/commands/upgrade/upgrade.ts +++ b/packages/cli/src/commands/upgrade/upgrade.ts @@ -19,10 +19,6 @@ const isConnected = (output: string): boolean => { return !output.includes('the host is inaccessible'); }; -const hasErrors = (output: string): boolean => output.includes('npm ERR'); - -const hasWarnings = (output: string): boolean => output.includes('npm WARN'); - const checkForErrors = (output: string): void => { if (!output) { return; @@ -33,11 +29,11 @@ const checkForErrors = (output: string): void => { ); } - if (hasErrors(output)) { + if (output.includes('npm ERR')) { throw new CLIError(`Upgrade failed with the following errors:\n${output}`); } - if (hasWarnings(output)) { + if (output.includes('npm WARN')) { logger.warn(output); } }; From 8b23e140fc9fba48a86f51207a6c357b888b99df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 17:38:12 +0100 Subject: [PATCH 32/35] revert uninstall changes as we're removing that in next version --- __e2e__/uninstall.test.ts | 5 +++-- .../cli/src/commands/install/uninstall.ts | 20 +------------------ 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/__e2e__/uninstall.test.ts b/__e2e__/uninstall.test.ts index 4d9e84968..748d46f5e 100644 --- a/__e2e__/uninstall.test.ts +++ b/__e2e__/uninstall.test.ts @@ -35,9 +35,10 @@ test('uninstall fails when package is not installed', () => { "dependencies": {} }`, }); - const {stderr} = run(DIR, ['uninstall', pkg], {expectedFailure: true}); + const {stderr, code} = run(DIR, ['uninstall', pkg], {expectedFailure: true}); - expect(stderr).toContain(`error Unknown package name "${pkg}".`); + expect(stderr).toContain(`Failed to unlink "${pkg}".`); + expect(code).toBe(1); }); test.each(['yarn', 'npm'])('uninstall module with %s', pm => { diff --git a/packages/cli/src/commands/install/uninstall.ts b/packages/cli/src/commands/install/uninstall.ts index 139cb189b..f5c46bf1b 100644 --- a/packages/cli/src/commands/install/uninstall.ts +++ b/packages/cli/src/commands/install/uninstall.ts @@ -6,31 +6,13 @@ * */ import {Config} from '@react-native-community/cli-types'; -import {logger, CLIError} from '@react-native-community/cli-tools'; +import {logger} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import unlink from '../link/unlink'; -import chalk from 'chalk'; async function uninstall(args: Array, ctx: Config): Promise { const name = args[0]; - if (!Object.keys(ctx.dependencies).includes(name)) { - logger.info( - `${chalk.bold( - 'We found the following dependencies installed in your project:\n', - )}${chalk.green.dim( - Object.keys(ctx.dependencies) - .map(dependency => ` - ${dependency}`) - .join('\n'), - )}`, - ); - throw new CLIError( - `Unknown package name "${chalk.bgRed.dim( - name, - )}". The package you are trying to uninstall is not present in your "package.json" dependencies.`, - ); - } - logger.info(`Unlinking "${name}"...`); await unlink.func([name], ctx, {}); From 37d4466961b5e7070b48356c2a5a8e9a17a5187b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 17:44:48 +0100 Subject: [PATCH 33/35] adjust copy --- packages/cli/src/commands/init/template.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/init/template.ts b/packages/cli/src/commands/init/template.ts index eecd19a1b..05128437b 100644 --- a/packages/cli/src/commands/init/template.ts +++ b/packages/cli/src/commands/init/template.ts @@ -38,10 +38,11 @@ export function getTemplateConfig( 'template.config.js', ); - logger.debug(`Getting config from ${configFilePath}.js`); + logger.debug(`Getting config from ${configFilePath}`); if (!fs.existsSync(configFilePath)) { throw new CLIError( - `Invalid template '${templateName}' specified. Make sure the template is CLI v2 compliant: ${chalk.underline.dim( + `Couldn't find the "${configFilePath} file inside "${templateName}" template. Please make sure the template is valid. + Read more: ${chalk.underline.dim( 'https://github.com/react-native-community/cli/blob/master/docs/init.md#creating-custom-template', )}`, ); From ea4ffd827cd6344d4f9c867ce64f5159526b2669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 28 Nov 2019 17:49:14 +0100 Subject: [PATCH 34/35] mock existsSync once --- .../init/__tests__/templateName.test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/commands/init/__tests__/templateName.test.ts b/packages/cli/src/commands/init/__tests__/templateName.test.ts index 51e515683..3e4baf999 100644 --- a/packages/cli/src/commands/init/__tests__/templateName.test.ts +++ b/packages/cli/src/commands/init/__tests__/templateName.test.ts @@ -5,19 +5,19 @@ const RN_NPM_PACKAGE = 'react-native'; const ABS_RN_PATH = '/path/to/react-native'; const ABS_RN_PATH_WINDOWS = 'path/to/react-native'; -test('supports file protocol with absolute path', async () => { +test('supports file protocol with absolute path', () => { jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => true); jest .spyOn(fs, 'readFileSync') .mockImplementationOnce(() => JSON.stringify({name: 'react-native'})); - expect(await processTemplateName(`file://${ABS_RN_PATH}`)).toEqual({ + expect(processTemplateName(`file://${ABS_RN_PATH}`)).toEqual({ uri: process.platform === 'win32' ? ABS_RN_PATH_WINDOWS : ABS_RN_PATH, name: RN_NPM_PACKAGE, }); }); -test('supports npm packages as template names', async () => { - expect(await processTemplateName(RN_NPM_PACKAGE)).toEqual({ +test('supports npm packages as template names', () => { + expect(processTemplateName(RN_NPM_PACKAGE)).toEqual({ uri: RN_NPM_PACKAGE, name: RN_NPM_PACKAGE, }); @@ -32,16 +32,16 @@ test.each` ${'@scoped/name@tag'} | ${'@scoped/name@tag'} | ${'@scoped/name'} `( 'supports versioned npm package "$templateName" as template name', - async ({templateName, uri, name}) => { - expect(await processTemplateName(templateName)).toEqual({uri, name}); + ({templateName, uri, name}) => { + expect(processTemplateName(templateName)).toEqual({uri, name}); }, ); -test('supports path to tgz archives', async () => { +test('supports path to tgz archives', () => { const ABS_RN_TARBALL_PATH = '/path/to/react-native/react-native-1.2.3-rc.0.tgz'; - jest.spyOn(fs, 'existsSync').mockImplementation(() => true); - expect(await processTemplateName(`file://${ABS_RN_TARBALL_PATH}`)).toEqual({ + jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => true); + expect(processTemplateName(`file://${ABS_RN_TARBALL_PATH}`)).toEqual({ uri: `file://${ABS_RN_TARBALL_PATH}`, name: 'react-native', }); From 398e7c4742783347f653d60e7a0aa4ec57f3c6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 2 Dec 2019 09:45:02 +0100 Subject: [PATCH 35/35] remove unused code --- .../src/commands/runAndroid/index.ts | 2 +- packages/tools/src/checkCommandExists.ts | 42 ------------------- packages/tools/src/index.ts | 1 - 3 files changed, 1 insertion(+), 44 deletions(-) delete mode 100644 packages/tools/src/checkCommandExists.ts diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index a90fdf25c..c9375608d 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -140,7 +140,7 @@ function buildAndRun(args: Flags) { ); let packageNameMatchArray = androidManifest.match(/package="(.+?)"/); - if (!packageNameMatchArray || packageNameMatchArray.length <= 0) { + if (!packageNameMatchArray || packageNameMatchArray.length === 0) { throw new CLIError( `Failed to build the app: No package name found. Found errors in ${chalk.underline.dim( `${appFolder}/src/main/AndroidManifest.xml`, diff --git a/packages/tools/src/checkCommandExists.ts b/packages/tools/src/checkCommandExists.ts deleted file mode 100644 index 2ae83605a..000000000 --- a/packages/tools/src/checkCommandExists.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {execSync} from 'child_process'; - -function commandExistsUnixSync(commandName: string) { - try { - const stdout = execSync( - `command -v ${commandName} 2>/dev/null` + - ` && { echo >&1 '${commandName} found'; exit 0; }`, - ); - return !!stdout; - } catch (error) { - return false; - } -} - -function commandExistsWindowsSync(commandName: string) { - if (/[\x00-\x1f<>:"\|\?\*]/.test(commandName)) { - return false; - } - try { - const stdout = execSync('where ' + commandName, {stdio: []}); - return !!stdout; - } catch (error) { - return false; - } -} - -function checkCommandExists(commandName: string) { - if (!commandName) { - return false; - } - switch (process.platform) { - case 'win32': - return commandExistsWindowsSync(commandName); - case 'darwin': - case 'linux': - return commandExistsUnixSync(commandName); - default: - return false; - } -} - -export default checkCommandExists; diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 5314d79e0..0a6f4fafa 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -3,6 +3,5 @@ export {default as groupFilesByType} from './groupFilesByType'; export {default as isPackagerRunning} from './isPackagerRunning'; export {default as getDefaultUserTerminal} from './getDefaultUserTerminal'; export {default as fetch} from './fetch'; -export {default as checkCommandExists} from './checkCommandExists'; export * from './errors';