xref: /expo/tools/src/commands/RemoveSDKVersion.ts (revision a272999e)
1import { Command } from '@expo/commander';
2import chalk from 'chalk';
3import inquirer from 'inquirer';
4import semver from 'semver';
5
6import {
7  Platform,
8  getSDKVersionsAsync,
9  getOldestSDKVersionAsync,
10  resolveSDKVersionAsync,
11} from '../ProjectVersions';
12import * as AndroidVersioning from '../versioning/android';
13import * as IosVersioning from '../versioning/ios';
14
15type ActionOptions = {
16  platform: Platform;
17  sdkVersion?: string;
18};
19
20const SUPPORTED_PLATFORMS: Platform[] = ['ios', 'android'];
21
22async function getOldestOrAskForSDKVersionAsync(platform: Platform): Promise<string | undefined> {
23  const sdkVersions = await getSDKVersionsAsync(platform);
24  const defaultSdkVersion = await getOldestSDKVersionAsync(platform);
25
26  if (defaultSdkVersion && process.env.CI) {
27    console.log(
28      `${chalk.red('`--sdkVersion`')} not provided - defaulting to ${chalk.cyan(defaultSdkVersion)}`
29    );
30    return defaultSdkVersion;
31  }
32
33  const { sdkVersion } = await inquirer.prompt<{ sdkVersion: string }>([
34    {
35      type: 'list',
36      name: 'sdkVersion',
37      message: 'What is the SDK version that you want to remove?',
38      default: defaultSdkVersion,
39      choices: sdkVersions,
40      validate(value) {
41        if (!semver.valid(value)) {
42          return `Invalid version: ${chalk.cyan(value)}`;
43        }
44        return true;
45      },
46    },
47  ]);
48  return sdkVersion;
49}
50
51async function askForPlatformAsync(): Promise<Platform> {
52  if (process.env.CI) {
53    throw new Error(`Run with \`--platform <${SUPPORTED_PLATFORMS.join(' | ')}>\`.`);
54  }
55
56  const { platform } = await inquirer.prompt<{ platform: Platform }>([
57    {
58      type: 'list',
59      name: 'platform',
60      message: 'Choose a platform from which you want to remove SDK version:',
61      default: SUPPORTED_PLATFORMS[0],
62      choices: SUPPORTED_PLATFORMS,
63    },
64  ]);
65
66  return platform;
67}
68
69async function action(options: ActionOptions) {
70  const platform = options.platform || (await askForPlatformAsync());
71  const sdkVersion =
72    (options.sdkVersion && (await resolveSDKVersionAsync(options.sdkVersion, options.platform))) ||
73    (await getOldestOrAskForSDKVersionAsync(options.platform));
74
75  if (!sdkVersion) {
76    throw new Error('Oldest SDK version not found. Try to run with `--sdkVersion <SDK version>`.');
77  }
78
79  switch (platform) {
80    case 'ios':
81      return IosVersioning.removeVersionAsync(sdkVersion);
82    case 'android':
83      return AndroidVersioning.removeVersionAsync(sdkVersion);
84    default:
85      throw new Error(`Platform '${platform}' is not supported.`);
86  }
87}
88
89export default (program: Command) => {
90  program
91    .command('remove-sdk-version')
92    .alias('remove-sdk', 'rm-sdk', 'rs')
93    .description('Removes SDK version.')
94    .usage(
95      `
96
97To remove versioned code for the oldest supported SDK on iOS, run:
98${chalk.gray('>')} ${chalk.italic.cyan('et remove-sdk-version --platform ios')}`
99    )
100    .option(
101      '-p, --platform <string>',
102      `Specifies a platform for which the SDK code should be removed. Supported platforms: ${SUPPORTED_PLATFORMS.map(
103        (platform) => chalk.cyan(platform)
104      ).join(', ')}.`
105    )
106    .option(
107      '-s, --sdkVersion [string]',
108      'SDK version to remove. Can be a full version name, major number, `latest` or `oldest` tag. Defaults to `oldest` on the CI.'
109    )
110    .asyncAction(action);
111};
112