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