1import { ModPlatform } from '@expo/config-plugins'; 2import assert from 'assert'; 3import chalk from 'chalk'; 4import fs from 'fs'; 5import path from 'path'; 6 7import * as Log from '../log'; 8import { CommandError } from '../utils/errors'; 9import { validateUrl } from '../utils/url'; 10 11export function resolvePackageManagerOptions(args: any) { 12 const managers: Record<string, boolean> = { 13 npm: args['--npm'], 14 yarn: args['--yarn'], 15 pnpm: args['--pnpm'], 16 }; 17 18 if ( 19 [managers.npm, managers.pnpm, managers.yarn, !!args['--no-install']].filter(Boolean).length > 1 20 ) { 21 throw new CommandError( 22 'BAD_ARGS', 23 'Specify at most one of: --no-install, --npm, --pnpm, --yarn' 24 ); 25 } 26 27 return managers; 28} 29 30/** Resolves a template option as a URL or file path pointing to a tar file. */ 31export function resolveTemplateOption(template: string) { 32 if (validateUrl(template)) { 33 return template; 34 } 35 const templatePath = path.resolve(template); 36 assert(fs.existsSync(templatePath), 'template file does not exist: ' + templatePath); 37 assert( 38 fs.statSync(templatePath).isFile(), 39 'template must be a tar file created by running `npm pack` in a project: ' + templatePath 40 ); 41 42 return templatePath; 43} 44 45/** Resolves dependencies to skip from a string joined by `,`. Example: `react-native,expo,lodash` */ 46export function resolveSkipDependencyUpdate(value: any) { 47 if (!value || typeof value !== 'string') { 48 return []; 49 } 50 return value.split(','); 51} 52 53/** Returns an array of platforms based on the input platform identifier and runtime constraints. */ 54export function resolvePlatformOption( 55 platform: string = 'all', 56 { loose }: { loose?: boolean } = {} 57): ModPlatform[] { 58 switch (platform) { 59 case 'ios': 60 return ['ios']; 61 case 'android': 62 return ['android']; 63 case 'all': 64 if (loose || process.platform !== 'win32') { 65 return ['android', 'ios']; 66 } 67 return ['android']; 68 default: 69 throw new CommandError(`Unsupported platform "${platform}". Options are: ios, android, all`); 70 } 71} 72 73/** Warns and filters out unsupported platforms based on the runtime constraints. Essentially this means no iOS on Windows devices. */ 74export function ensureValidPlatforms(platforms: ModPlatform[]): ModPlatform[] { 75 // Skip ejecting for iOS on Windows 76 if (process.platform === 'win32' && platforms.includes('ios')) { 77 Log.warn( 78 chalk`⚠️ Skipping generating the iOS native project files. Run {bold expo eject} again from macOS or Linux to generate the iOS project.\n` 79 ); 80 return platforms.filter((platform) => platform !== 'ios'); 81 } 82 return platforms; 83} 84 85/** Asserts platform length must be greater than zero. */ 86export function assertPlatforms(platforms: ModPlatform[]) { 87 if (!platforms?.length) { 88 throw new CommandError('At least one platform must be enabled when syncing'); 89 } 90} 91