1/** 2 * A helper script to load the Expo config and loaded plugins from a project 3 */ 4 5import fs from 'fs/promises'; 6import module from 'module'; 7import path from 'path'; 8import resolveFrom from 'resolve-from'; 9 10import { DEFAULT_IGNORE_PATHS } from '../Options'; 11import { isIgnoredPath } from '../utils/Path'; 12 13async function runAsync(programName: string, args: string[] = []) { 14 if (args.length < 1) { 15 console.log(`Usage: ${programName} <projectRoot> [ignoredFile]`); 16 return; 17 } 18 19 const projectRoot = path.resolve(args[0]); 20 const ignoredFile = args[1] ? path.resolve(args[1]) : null; 21 22 // @ts-expect-error: module internal _cache 23 const loadedModulesBefore = new Set(Object.keys(module._cache)); 24 25 const { getConfig } = require(resolveFrom(path.resolve(projectRoot), 'expo/config')); 26 const config = await getConfig(projectRoot, { skipSDKVersionRequirement: true }); 27 // @ts-expect-error: module internal _cache 28 const loadedModules = Object.keys(module._cache) 29 .filter((modulePath) => !loadedModulesBefore.has(modulePath)) 30 .map((modulePath) => path.relative(projectRoot, modulePath)); 31 32 const ignoredPaths = await loadIgnoredPathsAsync(ignoredFile); 33 const filteredLoadedModules = loadedModules.filter( 34 (modulePath) => !isIgnoredPath(modulePath, ignoredPaths) 35 ); 36 console.log(JSON.stringify({ config, loadedModules: filteredLoadedModules })); 37} 38 39// If running from the command line 40if (require.main?.filename === __filename) { 41 (async () => { 42 const programIndex = process.argv.findIndex((arg) => arg === __filename); 43 try { 44 await runAsync(process.argv[programIndex], process.argv.slice(programIndex + 1)); 45 } catch (e) { 46 console.error('Uncaught Error', e); 47 process.exit(1); 48 } 49 })(); 50} 51 52/** 53 * Load the generated ignored paths file from caller and remove the file after loading 54 */ 55async function loadIgnoredPathsAsync(ignoredFile: string | null) { 56 if (!ignoredFile) { 57 return DEFAULT_IGNORE_PATHS; 58 } 59 60 const ignorePaths = []; 61 try { 62 const fingerprintIgnore = await fs.readFile(ignoredFile, 'utf8'); 63 const fingerprintIgnoreLines = fingerprintIgnore.split('\n'); 64 for (const line of fingerprintIgnoreLines) { 65 const trimmedLine = line.trim(); 66 if (trimmedLine) { 67 ignorePaths.push(trimmedLine); 68 } 69 } 70 } catch {} 71 72 try { 73 await fs.rm(ignoredFile); 74 } catch {} 75 76 return ignorePaths; 77} 78 79/** 80 * Get the path to the ExpoConfigLoader file. 81 */ 82export function getExpoConfigLoaderPath() { 83 return path.join(__dirname, 'ExpoConfigLoader.js'); 84} 85