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: 31 | PackageManager.NpmPackageManager 32 | PackageManager.YarnPackageManager 33 | PackageManager.PnpmPackageManager; 34 35 /** How the check should resolve */ 36 options: Pick<Options, 'fix'>; 37 /** 38 * Extra parameters to pass to the `packageManager` when installing versioned packages. 39 * @example ['--no-save'] 40 */ 41 packageManagerArguments: string[]; 42 } 43) { 44 // Read the project Expo config without plugins. 45 const { exp, pkg } = getConfig(projectRoot, { 46 // Sometimes users will add a plugin to the config before installing the library, 47 // this wouldn't work unless we dangerously disable plugin serialization. 48 skipPlugins: true, 49 }); 50 51 const dependencies = await getVersionedDependenciesAsync(projectRoot, exp, pkg, packages); 52 53 if (!dependencies.length) { 54 Log.exit(chalk.greenBright('Dependencies are up to date'), 0); 55 } 56 57 logIncorrectDependencies(dependencies); 58 59 const value = 60 // If `--fix` then always fix. 61 fix || 62 // Otherwise prompt to fix when not running in CI. 63 (!env.CI && (await confirmAsync({ message: 'Fix dependencies?' }).catch(() => false))); 64 65 if (value) { 66 // Just pass in the names, the install function will resolve the versions again. 67 const fixedDependencies = dependencies.map((dependency) => dependency.packageName); 68 Log.debug('Installing fixed dependencies:', fixedDependencies); 69 // Install the corrected dependencies. 70 return installPackagesAsync(projectRoot, { 71 packageManager, 72 packages: fixedDependencies, 73 packageManagerArguments, 74 sdkVersion: exp.sdkVersion!, 75 }); 76 } 77 // Exit with non-zero exit code if any of the dependencies are out of date. 78 Log.exit(chalk.red('Found outdated dependencies'), 1); 79} 80