1import { Command } from '@expo/commander'; 2import chalk from 'chalk'; 3import inquirer from 'inquirer'; 4import semver from 'semver'; 5 6import { Platform, getNextSDKVersionAsync } from '../ProjectVersions'; 7import * as AndroidVersioning from '../versioning/android'; 8import * as IosVersioning from '../versioning/ios'; 9 10type ActionOptions = { 11 platform: Platform; 12 sdkVersion?: string; 13 filenames?: string; 14 vendored: string[]; 15 reinstall?: boolean; 16 preventReinstall?: boolean; 17 package?: string; 18}; 19 20async function getNextOrAskForSDKVersionAsync(platform: Platform): Promise<string | undefined> { 21 const defaultSdkVersion = await getNextSDKVersionAsync(platform); 22 23 if (defaultSdkVersion && process.env.CI) { 24 console.log( 25 `${chalk.red('`--sdkVersion`')} not provided - defaulting to ${chalk.cyan(defaultSdkVersion)}` 26 ); 27 return defaultSdkVersion; 28 } 29 30 const { sdkVersion } = await inquirer.prompt<{ sdkVersion: string }>([ 31 { 32 type: 'input', 33 name: 'sdkVersion', 34 message: 'What is the SDK version that you want to add?', 35 default: defaultSdkVersion, 36 validate(value) { 37 if (!semver.valid(value)) { 38 return `Invalid version: ${chalk.cyan(value)}`; 39 } 40 return true; 41 }, 42 }, 43 ]); 44 return sdkVersion; 45} 46 47async function action(options: ActionOptions) { 48 if (!options.platform) { 49 throw new Error('Run with `--platform <ios | android>`.'); 50 } 51 52 const sdkVersion = options.sdkVersion || (await getNextOrAskForSDKVersionAsync(options.platform)); 53 54 if (!sdkVersion) { 55 throw new Error('Next SDK version not found. Try to run with `--sdkVersion <SDK version>`.'); 56 } 57 const sdkNumber = semver.major(sdkVersion); 58 59 switch (options.platform) { 60 case 'ios': 61 if (options.vendored.length > 0) { 62 await IosVersioning.versionVendoredModulesAsync(sdkNumber, options.vendored); 63 } else if (options.filenames) { 64 await IosVersioning.versionReactNativeIOSFilesAsync(options.filenames, sdkVersion); 65 } else if (options.package) { 66 await IosVersioning.regenerateVersionedPackageAsync(sdkVersion, options.package); 67 } else { 68 await IosVersioning.versionVendoredModulesAsync(sdkNumber, null); 69 await IosVersioning.addVersionAsync(sdkVersion); 70 } 71 await IosVersioning.reinstallPodsAsync(options.reinstall, options.preventReinstall); 72 return; 73 case 'android': 74 return AndroidVersioning.addVersionAsync(sdkVersion); 75 default: 76 throw new Error(`Platform '${options.platform}' is not supported.`); 77 } 78} 79 80export default (program: Command) => { 81 program 82 .command('add-sdk-version') 83 .alias('add-sdk') 84 .description('Versions code for the new SDK version.') 85 .usage( 86 ` 87 88To version code for the new SDK on iOS, run: 89${chalk.gray('>')} ${chalk.italic.cyan('et add-sdk-version --platform ios')} 90 91To backport changes made in unversioned code into already versioned SDK, run: 92${chalk.gray('>')} ${chalk.italic.cyan( 93 'et add-sdk-version --platform ios --sdkVersion XX.0.0 --filenames */some/glob/expression/**' 94 )}` 95 ) 96 .option( 97 '-p, --platform <string>', 98 `Specifies a platform for which the SDK code should be generated. Supported platforms: ${chalk.cyan( 99 'ios' 100 )}.` 101 ) 102 .option( 103 '-s, --sdkVersion [string]', 104 'SDK version to add. Defaults to the newest SDK version increased by a major update.' 105 ) 106 .option( 107 '-f, --filenames [string]', 108 'Glob pattern of file paths to version. Useful when you want to backport unversioned code into already versioned SDK. Optional. When provided, option `--sdkVersion` is required.' 109 ) 110 .option( 111 '-v, --vendored <string>', 112 'Name of the vendored module to (re)version. iOS only.', 113 (value, previous) => (previous ?? []).concat(value), 114 [] 115 ) 116 .option( 117 '-r, --reinstall', 118 'Whether to force reinstalling pods after generating a new version. iOS only.' 119 ) 120 .option( 121 '--prevent-reinstall', 122 'Whether to force not reinstalling pods after generating a new version. iOS only.' 123 ) 124 .option( 125 '-x, --package [string]', 126 'Only generate a specific package. When provided, option `--sdkVersion` is required.' 127 ) 128 .asyncAction(action); 129}; 130