diff --git a/packages/cli-types/src/index.ts b/packages/cli-types/src/index.ts index 15eca2521..1839f151d 100644 --- a/packages/cli-types/src/index.ts +++ b/packages/cli-types/src/index.ts @@ -13,14 +13,16 @@ import { export type InquirerPrompt = any; -export interface Command { +export type CommandFunction = ( + argv: Array, + ctx: Config, + args: Args, +) => Promise | void; + +export interface Command { name: string; description?: string; - func: ( - argv: Array, - ctx: Config, - args: Object, - ) => Promise | void; + func: CommandFunction; options?: Array<{ name: string; description?: string; diff --git a/packages/cli/src/commands/doctor/doctor.js b/packages/cli/src/commands/doctor/doctor.ts similarity index 76% rename from packages/cli/src/commands/doctor/doctor.js rename to packages/cli/src/commands/doctor/doctor.ts index dfc11c47b..ec28c6bbf 100644 --- a/packages/cli/src/commands/doctor/doctor.js +++ b/packages/cli/src/commands/doctor/doctor.ts @@ -1,18 +1,19 @@ -// @flow import chalk from 'chalk'; +// @ts-ignore import envinfo from 'envinfo'; import {logger} from '@react-native-community/cli-tools'; -// $FlowFixMe - converted to TS import {getHealthchecks, HEALTHCHECK_TYPES} from './healthchecks'; -// $FlowFixMe - converted to TS import {getLoader} from '../../tools/loader'; -// $FlowFixMe - converted to TS import printFixOptions, {KEYS} from './printFixOptions'; import runAutomaticFix, {AUTOMATIC_FIX_LEVELS} from './runAutomaticFix'; -import type {ConfigT} from 'types'; -import type {HealthCheckInterface} from './types'; - -const printCategory = ({label, key}) => { +import {CommandFunction} from '@react-native-community/cli-types'; +import { + HealthCheckCategory, + HealthCheckCategoryResult, + HealthCheckResult, +} from './types'; + +const printCategory = ({label, key}: {label: string; key: number}) => { if (key > 0) { logger.log(); } @@ -25,12 +26,7 @@ const printIssue = ({ needsToBeFixed, isRequired, description, -}: { - label: string, - needsToBeFixed: boolean, - isRequired: boolean, - description: string, -}) => { +}: HealthCheckResult) => { const symbol = needsToBeFixed ? isRequired ? chalk.red('✖') @@ -40,21 +36,23 @@ const printIssue = ({ logger.log(` ${symbol} ${label}${needsToBeFixed ? ': ' + description : ''}`); }; -const printOverallStats = ({errors, warnings}) => { +const printOverallStats = ({ + errors, + warnings, +}: { + errors: number; + warnings: number; +}) => { logger.log(`\n${chalk.bold('Errors:')} ${errors}`); logger.log(`${chalk.bold('Warnings:')} ${warnings}`); }; type FlagsT = { - fix: boolean | void, - contributor: boolean | void, + fix: boolean | void; + contributor: boolean | void; }; -export default (async function runDoctor( - argv: Array, - ctx: ConfigT, - options: FlagsT, -) { +export default (async (_, __, options) => { const Loader = getLoader(); const loader = new Loader(); @@ -76,10 +74,7 @@ export default (async function runDoctor( const iterateOverHealthChecks = async ({ label, healthchecks, - }: { - label: string, - healthchecks: Array, - }) => ({ + }: HealthCheckCategory): Promise => ({ label, healthchecks: (await Promise.all( healthchecks.map(async healthcheck => { @@ -108,23 +103,22 @@ export default (async function runDoctor( : undefined, }; }), - )).filter(Boolean), + )).filter(healthcheck => healthcheck !== undefined) as HealthCheckResult[], }); // Remove all the categories that don't have any healthcheck with `needsToBeFixed` // so they don't show when the user taps to fix encountered issues - const removeFixedCategories = categories => + const removeFixedCategories = (categories: HealthCheckCategoryResult[]) => categories.filter(category => category.healthchecks.some(healthcheck => healthcheck.needsToBeFixed), ); - const iterateOverCategories = categories => - // $FlowFixMe - bad Object.values typings + const iterateOverCategories = (categories: HealthCheckCategory[]) => Promise.all(categories.map(iterateOverHealthChecks)); - const healthchecksPerCategory = await iterateOverCategories( - Object.values(getHealthchecks(options)), - ); + const healthchecksPerCategory = await iterateOverCategories(Object.values( + getHealthchecks(options), + ).filter(category => category !== undefined) as HealthCheckCategory[]); loader.stop(); @@ -136,15 +130,17 @@ export default (async function runDoctor( healthchecksPerCategory.forEach((issueCategory, key) => { printCategory({...issueCategory, key}); - issueCategory.healthchecks.map(healthcheck => { + issueCategory.healthchecks.forEach(healthcheck => { printIssue(healthcheck); if (healthcheck.type === HEALTHCHECK_TYPES.WARNING) { - return stats.warnings++; + stats.warnings++; + return; } if (healthcheck.type === HEALTHCHECK_TYPES.ERROR) { - return stats.errors++; + stats.errors++; + return; } }); }); @@ -161,13 +157,15 @@ export default (async function runDoctor( }); } - const onKeyPress = async key => { - // $FlowFixMe - process.stdin.setRawMode(false); + const onKeyPress = async (key: string) => { + if (typeof process.stdin.setRawMode === 'function') { + process.stdin.setRawMode(false); + } process.stdin.removeAllListeners('data'); if (key === KEYS.EXIT || key === '\u0003') { - return process.exit(0); + process.exit(0); + return; } if ( @@ -197,4 +195,4 @@ export default (async function runDoctor( }; printFixOptions({onKeyPress}); -}); +}) as CommandFunction; diff --git a/packages/cli/src/commands/doctor/healthchecks/index.ts b/packages/cli/src/commands/doctor/healthchecks/index.ts index b439dfd2d..1b213097b 100644 --- a/packages/cli/src/commands/doctor/healthchecks/index.ts +++ b/packages/cli/src/commands/doctor/healthchecks/index.ts @@ -7,6 +7,7 @@ import androidNDK from './androidNDK'; import xcode from './xcode'; import cocoaPods from './cocoaPods'; import iosDeploy from './iosDeploy'; +import {Healthchecks} from '../types'; export const HEALTHCHECK_TYPES = { ERROR: 'ERROR', @@ -18,7 +19,7 @@ type Options = { contributor: boolean | void; }; -export const getHealthchecks = ({contributor}: Options) => ({ +export const getHealthchecks = ({contributor}: Options): Healthchecks => ({ common: { label: 'Common', healthchecks: [ diff --git a/packages/cli/src/commands/doctor/index.js b/packages/cli/src/commands/doctor/index.ts similarity index 98% rename from packages/cli/src/commands/doctor/index.js rename to packages/cli/src/commands/doctor/index.ts index b1539f635..41ba25b8a 100644 --- a/packages/cli/src/commands/doctor/index.js +++ b/packages/cli/src/commands/doctor/index.ts @@ -1,4 +1,3 @@ -// @flow import doctor from './doctor'; export default { diff --git a/packages/cli/src/commands/doctor/runAutomaticFix.js b/packages/cli/src/commands/doctor/runAutomaticFix.ts similarity index 67% rename from packages/cli/src/commands/doctor/runAutomaticFix.js rename to packages/cli/src/commands/doctor/runAutomaticFix.ts index fbf14ad59..f58a25000 100644 --- a/packages/cli/src/commands/doctor/runAutomaticFix.js +++ b/packages/cli/src/commands/doctor/runAutomaticFix.ts @@ -1,38 +1,41 @@ -// @flow import chalk from 'chalk'; -import ora from 'ora'; +import ora, {Ora} from 'ora'; import {logger} from '@react-native-community/cli-tools'; -// $FlowFixMe - converted to TS import {HEALTHCHECK_TYPES} from './healthchecks'; -import type {EnvironmentInfo} from './types'; +import {EnvironmentInfo, HealthCheckCategoryResult} from './types'; -const AUTOMATIC_FIX_LEVELS = { - ALL_ISSUES: 'ALL_ISSUES', - ERRORS: 'ERRORS', - WARNINGS: 'WARNINGS', -}; +export enum AUTOMATIC_FIX_LEVELS { + ALL_ISSUES = 'ALL_ISSUES', + ERRORS = 'ERRORS', + WARNINGS = 'WARNINGS', +} -export {AUTOMATIC_FIX_LEVELS}; -export default async ({ +interface RunAutomaticFixArgs { + healthchecks: HealthCheckCategoryResult[]; + automaticFixLevel: AUTOMATIC_FIX_LEVELS; + stats: { + errors: number; + warnings: number; + }; + loader: Ora; + environmentInfo: EnvironmentInfo; +} + +export default async function({ healthchecks, automaticFixLevel, stats, - loader, environmentInfo, -}: { - healthchecks: any, - automaticFixLevel: $Values, - stats: {errors: any, warnings: any}, - loader: typeof ora, - environmentInfo: EnvironmentInfo, -}) => { +}: RunAutomaticFixArgs) { // Remove the fix options from screen - // $FlowFixMe - process.stdout.moveCursor(0, -6); - // $FlowFixMe - process.stdout.clearScreenDown(); + if (process.stdout.isTTY) { + // @ts-ignore + process.stdout.moveCursor(0, -6); + // @ts-ignore + process.stdout.clearScreenDown(); + } - const totalIssuesBasedOnFixLevel = { + const totalIssuesBasedOnFixLevel: {[x in AUTOMATIC_FIX_LEVELS]: number} = { [AUTOMATIC_FIX_LEVELS.ALL_ISSUES]: stats.errors + stats.warnings, [AUTOMATIC_FIX_LEVELS.ERRORS]: stats.errors, [AUTOMATIC_FIX_LEVELS.WARNINGS]: stats.warnings, @@ -40,7 +43,7 @@ export default async ({ const issuesCount = totalIssuesBasedOnFixLevel[automaticFixLevel]; logger.log( - `\nAttempting to fix ${chalk.bold(issuesCount)} issue${ + `\nAttempting to fix ${chalk.bold(issuesCount.toString())} issue${ issuesCount > 1 ? 's' : '' }...`, ); @@ -64,6 +67,8 @@ export default async ({ healthcheck.type === HEALTHCHECK_TYPES.WARNING ); } + + return; }); if (!healthchecksToRun.length) { @@ -88,4 +93,4 @@ export default async ({ } } } -}; +} diff --git a/packages/cli/src/commands/doctor/types.js b/packages/cli/src/commands/doctor/types.js deleted file mode 100644 index 3793e8d9b..000000000 --- a/packages/cli/src/commands/doctor/types.js +++ /dev/null @@ -1,79 +0,0 @@ -// @flow -import Ora from 'ora'; - -export type EnvironmentInfo = { - System: { - OS: string, - CPU: string, - Memory: string, - Shell: { - version: string, - path: string, - }, - }, - Binaries: { - Node: { - version: string, - path: string, - }, - Yarn: { - version: string, - path: string, - }, - npm: { - version: string, - path: string, - }, - Watchman: { - version: string, - path: string, - }, - }, - SDKs: { - 'iOS SDK': { - Platforms: string[], - }, - 'Android SDK': { - 'API Levels': string[], - 'Build Tools': string[], - 'System Images': string[], - 'Android NDK': string, - }, - }, - IDEs: { - 'Android Studio': string, - Emacs: { - version: string, - path: string, - }, - Nano: { - version: string, - path: string, - }, - VSCode: { - version: string, - path: string, - }, - Vim: { - version: string, - path: string, - }, - Xcode: { - version: string, - path: string, - }, - }, -}; - -export type HealthCheckInterface = { - label: string, - visible?: boolean | void, - isRequired?: boolean, - getDiagnostics: ( - environmentInfo: EnvironmentInfo, - ) => Promise<{version?: string, needsToBeFixed: boolean | string}>, - runAutomaticFix: (args: { - loader: typeof Ora, - environmentInfo: EnvironmentInfo, - }) => Promise | void, -}; diff --git a/packages/cli/src/commands/doctor/types.ts b/packages/cli/src/commands/doctor/types.ts index 07ed78a84..b710eaa17 100644 --- a/packages/cli/src/commands/doctor/types.ts +++ b/packages/cli/src/commands/doctor/types.ts @@ -66,6 +66,22 @@ export type EnvironmentInfo = { }; }; +export type HealthCheckCategory = { + label: string; + healthchecks: HealthCheckInterface[]; +}; + +export type Healthchecks = { + common: HealthCheckCategory; + android: HealthCheckCategory; + ios?: HealthCheckCategory; +}; + +export type RunAutomaticFix = (args: { + loader: Ora; + environmentInfo: EnvironmentInfo; +}) => Promise | void; + export type HealthCheckInterface = { label: string; visible?: boolean | void; @@ -73,8 +89,19 @@ export type HealthCheckInterface = { getDiagnostics: ( environmentInfo: EnvironmentInfo, ) => Promise<{version?: string; needsToBeFixed: boolean | string}>; - runAutomaticFix: (args: { - loader: Ora; - environmentInfo: EnvironmentInfo; - }) => Promise | void; + runAutomaticFix: RunAutomaticFix; +}; + +export type HealthCheckResult = { + label: string; + needsToBeFixed: boolean; + description: string; + runAutomaticFix: RunAutomaticFix; + isRequired: boolean; + type?: string; +}; + +export type HealthCheckCategoryResult = { + label: string; + healthchecks: HealthCheckResult[]; };