1import { getExpoHomeDirectory } from '@expo/config/build/getUserState'; 2import path from 'path'; 3import ProgressBar from 'progress'; 4 5import { getReleasedVersionsAsync, SDKVersion } from '../api/getVersions'; 6import * as Log from '../log'; 7import { downloadAppAsync } from './downloadAppAsync'; 8import { CommandError } from './errors'; 9import { profile } from './profile'; 10import { setProgressBar } from './progress'; 11 12const platformSettings: Record< 13 string, 14 { 15 shouldExtractResults: boolean; 16 versionsKey: keyof SDKVersion; 17 getFilePath: (filename: string) => string; 18 } 19> = { 20 ios: { 21 versionsKey: 'iosClientUrl', 22 getFilePath: (filename) => 23 path.join(getExpoHomeDirectory(), 'ios-simulator-app-cache', `${filename}.app`), 24 shouldExtractResults: true, 25 }, 26 android: { 27 versionsKey: 'androidClientUrl', 28 getFilePath: (filename) => 29 path.join(getExpoHomeDirectory(), 'android-apk-cache', `${filename}.apk`), 30 shouldExtractResults: false, 31 }, 32}; 33 34/** Download the Expo Go app from the Expo servers (if only it was this easy for every app). */ 35export async function downloadExpoGoAsync( 36 platform: keyof typeof platformSettings, 37 { 38 url, 39 sdkVersion, 40 }: { 41 url?: string; 42 sdkVersion?: string; 43 } 44): Promise<string> { 45 const { getFilePath, versionsKey, shouldExtractResults } = platformSettings[platform]; 46 47 const bar = new ProgressBar('Downloading the Expo Go app [:bar] :percent :etas', { 48 width: 64, 49 total: 100, 50 clear: true, 51 complete: '=', 52 incomplete: ' ', 53 }); 54 // TODO: Auto track progress 55 setProgressBar(bar); 56 57 if (!url) { 58 if (!sdkVersion) { 59 throw new CommandError( 60 `Unable to determine which Expo Go version to install (platform: ${platform})` 61 ); 62 } 63 const versions = await getReleasedVersionsAsync(); 64 const version = versions[sdkVersion]; 65 Log.debug(`Installing Expo Go version for SDK ${sdkVersion} at URL: ${version[versionsKey]}`); 66 url = version[versionsKey] as string; 67 } 68 69 const filename = path.parse(url).name; 70 71 try { 72 const outputPath = getFilePath(filename); 73 Log.debug(`Downloading Expo Go from "${url}" to "${outputPath}".`); 74 Log.debug( 75 `The requested copy of Expo Go might already be cached in: "${getExpoHomeDirectory()}". You can disable the cache with EXPO_NO_CACHE=1` 76 ); 77 await profile(downloadAppAsync)({ 78 url, 79 // Save all encrypted cache data to `~/.expo/expo-go` 80 cacheDirectory: 'expo-go', 81 outputPath, 82 extract: shouldExtractResults, 83 onProgress({ progress }) { 84 if (bar) { 85 bar.tick(1, progress); 86 } 87 }, 88 }); 89 return outputPath; 90 } finally { 91 bar.terminate(); 92 setProgressBar(null); 93 } 94} 95