1import { getExpoHomeDirectory } from '@expo/config/build/getUserState'; 2import path from 'path'; 3 4import { getVersionsAsync, SDKVersion } from '../api/getVersions'; 5import { downloadAppAsync } from './downloadAppAsync'; 6import { CommandError } from './errors'; 7import { profile } from './profile'; 8import { createProgressBar } from './progress'; 9 10const debug = require('debug')('expo:utils:downloadExpoGo') as typeof console.log; 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 = createProgressBar('Downloading the Expo Go app [:bar] :percent :etas', { 48 width: 64, 49 total: 100, 50 clear: true, 51 complete: '=', 52 incomplete: ' ', 53 }); 54 55 if (!url) { 56 if (!sdkVersion) { 57 throw new CommandError( 58 `Unable to determine which Expo Go version to install (platform: ${platform})` 59 ); 60 } 61 const { sdkVersions: versions } = await getVersionsAsync(); 62 63 const version = versions[sdkVersion]; 64 if (!version) { 65 throw new CommandError( 66 `Unable to find a version of Expo Go for SDK ${sdkVersion} (platform: ${platform})` 67 ); 68 } 69 debug(`Installing Expo Go version for SDK ${sdkVersion} at URL: ${version[versionsKey]}`); 70 url = version[versionsKey] as string; 71 } 72 73 const filename = path.parse(url).name; 74 75 try { 76 const outputPath = getFilePath(filename); 77 debug(`Downloading Expo Go from "${url}" to "${outputPath}".`); 78 debug( 79 `The requested copy of Expo Go might already be cached in: "${getExpoHomeDirectory()}". You can disable the cache with EXPO_NO_CACHE=1` 80 ); 81 await profile(downloadAppAsync)({ 82 url, 83 // Save all encrypted cache data to `~/.expo/expo-go` 84 cacheDirectory: 'expo-go', 85 outputPath, 86 extract: shouldExtractResults, 87 onProgress({ progress }) { 88 if (bar) { 89 bar.tick(1, progress); 90 } 91 }, 92 }); 93 return outputPath; 94 } finally { 95 bar?.terminate(); 96 } 97} 98