1import { Command } from '@expo/commander'; 2import spawnAsync from '@expo/spawn-async'; 3import chalk from 'chalk'; 4 5import { ANDROID_DIR } from '../Constants'; 6import { getNextSDKVersionAsync } from '../ProjectVersions'; 7 8type ActionOptions = { 9 checkout?: string; 10 sdkVersion?: string; 11}; 12 13async function updateReactAndroidAsync(sdkVersion: string): Promise<void> { 14 console.log( 15 `Running ${chalk.blue('ReactAndroidCodeTransformer')} with ${chalk.yellow( 16 `./gradlew :tools:execute --args ${sdkVersion}` 17 )} command...` 18 ); 19 await spawnAsync('./gradlew', [':tools:execute', '--args', sdkVersion], { 20 cwd: ANDROID_DIR, 21 stdio: 'inherit', 22 }); 23} 24 25async function action(options: ActionOptions) { 26 // When we're updating React Native, we mostly want it to be for the next SDK that isn't versioned yet. 27 const androidSdkVersion = options.sdkVersion || (await getNextSDKVersionAsync('android')); 28 29 if (!androidSdkVersion) { 30 throw new Error( 31 'Cannot obtain next SDK version. Try to run with --sdkVersion <sdkVersion> flag.' 32 ); 33 } 34 35 console.log( 36 `Updating ${chalk.green('ReactAndroid')} for SDK ${chalk.cyan(androidSdkVersion)} ...` 37 ); 38 await updateReactAndroidAsync(androidSdkVersion); 39} 40 41export default (program: Command) => { 42 program 43 .command('update-react-native') 44 .alias('update-rn', 'urn') 45 .description( 46 'Updates React Native submodule and applies Expo-specific code transformations on ReactAndroid and ReactCommon folders.' 47 ) 48 .option( 49 '-s, --sdkVersion [string]', 50 'SDK version for which the forked React Native will be used. Defaults to the newest SDK version increased by a major update.' 51 ) 52 .asyncAction(action); 53}; 54