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 bun: args['--bun'], 17 }; 18 19 if ( 20 [managers.npm, managers.pnpm, managers.yarn, managers.bun, !!args['--no-install']].filter( 21 Boolean 22 ).length > 1 23 ) { 24 throw new CommandError( 25 'BAD_ARGS', 26 'Specify at most one of: --no-install, --npm, --pnpm, --yarn, --bun' 27 ); 28 } 29 30 return managers; 31} 32 33/** Resolves a template option as a URL or file path pointing to a tar file. */ 34export function resolveTemplateOption(template: string) { 35 if (validateUrl(template)) { 36 return template; 37 } 38 const templatePath = path.resolve(template); 39 assert(fs.existsSync(templatePath), 'template file does not exist: ' + templatePath); 40 assert( 41 fs.statSync(templatePath).isFile(), 42 'template must be a tar file created by running `npm pack` in a project: ' + templatePath 43 ); 44 45 return templatePath; 46} 47 48/** Resolves dependencies to skip from a string joined by `,`. Example: `react-native,expo,lodash` */ 49export function resolveSkipDependencyUpdate(value: any) { 50 if (!value || typeof value !== 'string') { 51 return []; 52 } 53 return value.split(','); 54} 55 56/** Returns an array of platforms based on the input platform identifier and runtime constraints. */ 57export function resolvePlatformOption( 58 platform: string = 'all', 59 { loose }: { loose?: boolean } = {} 60): ModPlatform[] { 61 switch (platform) { 62 case 'ios': 63 return ['ios']; 64 case 'android': 65 return ['android']; 66 case 'all': 67 return loose || process.platform !== 'win32' ? ['android', 'ios'] : ['android']; 68 default: 69 return [platform as ModPlatform]; 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