1import resolveFrom from 'resolve-from'; 2 3// These resolvers enable us to test the CLI in older projects. 4// We may be able to get rid of this in the future. 5// TODO: Maybe combine with AsyncResolver? 6class MetroImportError extends Error { 7 constructor(projectRoot: string, moduleId: string) { 8 super( 9 `Missing package "${moduleId}" in the project at: ${projectRoot}\n` + 10 'This usually means "react-native" is not installed. ' + 11 'Please verify that dependencies in package.json include "react-native" ' + 12 'and run `yarn` or `npm install`.' 13 ); 14 } 15} 16 17function resolveFromProject(projectRoot: string, moduleId: string) { 18 const resolvedPath = resolveFrom.silent(projectRoot, moduleId); 19 if (!resolvedPath) { 20 throw new MetroImportError(projectRoot, moduleId); 21 } 22 return resolvedPath; 23} 24 25function importFromProject(projectRoot: string, moduleId: string) { 26 return require(resolveFromProject(projectRoot, moduleId)); 27} 28 29/** Import `metro` from the project. */ 30export function importMetroFromProject(projectRoot: string): typeof import('metro') { 31 return importFromProject(projectRoot, 'metro'); 32} 33 34/** Import `@expo/metro-config` from the project. */ 35export function importExpoMetroConfigFromProject( 36 projectRoot: string 37): typeof import('@expo/metro-config') { 38 return importFromProject(projectRoot, '@expo/metro-config'); 39} 40