1import { getConfig, Platform } from '@expo/config'; 2 3import { getPlatformBundlers, PlatformBundlers } from '../start/server/platformBundlers'; 4import { CommandError } from '../utils/errors'; 5 6export type Options = { 7 outputDir: string; 8 platforms: Platform[]; 9 maxWorkers?: number; 10 dev: boolean; 11 clear: boolean; 12 minify: boolean; 13 dumpAssetmap: boolean; 14 dumpSourcemap: boolean; 15}; 16 17/** Returns an array of platforms based on the input platform identifier and runtime constraints. */ 18export function resolvePlatformOption( 19 platformBundlers: PlatformBundlers, 20 platform: string[] = ['all'] 21): Platform[] { 22 const platformsAvailable: Partial<PlatformBundlers> = Object.fromEntries( 23 Object.entries(platformBundlers).filter(([, bundler]) => bundler === 'metro') 24 ); 25 26 if (!Object.keys(platformsAvailable).length) { 27 throw new CommandError( 28 `No platforms are configured to use the Metro bundler in the project Expo config.` 29 ); 30 } 31 32 const assertPlatformBundler = (platform: Platform): Platform => { 33 if (!platformsAvailable[platform]) { 34 throw new CommandError( 35 'BAD_ARGS', 36 `Platform "${platform}" is not configured to use the Metro bundler in the project Expo config.` 37 ); 38 } 39 40 return platform; 41 }; 42 43 const knownPlatforms = ['android', 'ios', 'web'] as Platform[]; 44 const assertPlatformIsKnown = (platform: string): Platform => { 45 if (!knownPlatforms.includes(platform as Platform)) { 46 throw new CommandError( 47 `Unsupported platform "${platform}". Options are: ${knownPlatforms.join(',')},all` 48 ); 49 } 50 51 return platform as Platform; 52 }; 53 54 return ( 55 platform 56 // Expand `all` to all available platforms. 57 .map((platform) => (platform === 'all' ? Object.keys(platformsAvailable) : platform)) 58 .flat() 59 // Remove duplicated platforms 60 .filter((platform, index, list) => list.indexOf(platform) === index) 61 // Assert platforms are valid 62 .map((platform) => assertPlatformIsKnown(platform)) 63 .map((platform) => assertPlatformBundler(platform)) 64 ); 65} 66 67export async function resolveOptionsAsync(projectRoot: string, args: any): Promise<Options> { 68 const { exp } = getConfig(projectRoot, { skipPlugins: true, skipSDKVersionRequirement: true }); 69 const platformBundlers = getPlatformBundlers(exp); 70 71 return { 72 platforms: resolvePlatformOption(platformBundlers, args['--platform']), 73 outputDir: args['--output-dir'] ?? 'dist', 74 minify: !args['--no-minify'], 75 clear: !!args['--clear'], 76 dev: !!args['--dev'], 77 maxWorkers: args['--max-workers'], 78 dumpAssetmap: !!args['--dump-assetmap'], 79 dumpSourcemap: !!args['--dump-sourcemap'], 80 }; 81} 82