1import { getConfig } from '@expo/config'; 2import * as PackageManager from '@expo/package-manager'; 3import chalk from 'chalk'; 4 5import * as Log from '../log'; 6import { 7 getVersionedDependenciesAsync, 8 logIncorrectDependencies, 9} from '../start/doctor/dependencies/validateDependenciesVersions'; 10import { env } from '../utils/env'; 11import { confirmAsync } from '../utils/prompts'; 12import { installPackagesAsync } from './installAsync'; 13import { Options } from './resolveOptions'; 14 15// Exposed for testing. 16export async function checkPackagesAsync( 17 projectRoot: string, 18 { 19 packages, 20 packageManager, 21 options: { fix }, 22 packageManagerArguments, 23 }: { 24 /** 25 * List of packages to version 26 * @example ['uuid', 'react-native-reanimated@latest'] 27 */ 28 packages: string[]; 29 /** Package manager to use when installing the versioned packages. */ 30 packageManager: PackageManager.NpmPackageManager | PackageManager.YarnPackageManager; 31 32 /** How the check should resolve */ 33 options: Pick<Options, 'fix'>; 34 /** 35 * Extra parameters to pass to the `packageManager` when installing versioned packages. 36 * @example ['--no-save'] 37 */ 38 packageManagerArguments: string[]; 39 } 40) { 41 // Read the project Expo config without plugins. 42 const { exp, pkg } = getConfig(projectRoot, { 43 // Sometimes users will add a plugin to the config before installing the library, 44 // this wouldn't work unless we dangerously disable plugin serialization. 45 skipPlugins: true, 46 }); 47 48 const dependencies = await getVersionedDependenciesAsync(projectRoot, exp, pkg, packages); 49 50 if (!dependencies.length) { 51 Log.exit(chalk.greenBright('Dependencies are up to date'), 0); 52 } 53 54 logIncorrectDependencies(dependencies); 55 56 const value = 57 // If `--fix` then always fix. 58 fix || 59 // Otherwise prompt to fix when not running in CI. 60 (!env.CI && (await confirmAsync({ message: 'Fix dependencies?' }).catch(() => false))); 61 62 if (value) { 63 // Just pass in the names, the install function will resolve the versions again. 64 const fixedDependencies = dependencies.map((dependency) => dependency.packageName); 65 Log.debug('Installing fixed dependencies:', fixedDependencies); 66 // Install the corrected dependencies. 67 return installPackagesAsync(projectRoot, { 68 packageManager, 69 packages: fixedDependencies, 70 packageManagerArguments, 71 sdkVersion: exp.sdkVersion!, 72 }); 73 } 74 // Exit with non-zero exit code if any of the dependencies are out of date. 75 Log.exit(chalk.red('Found outdated dependencies'), 1); 76} 77