1import { getConfig, Platform } from '@expo/config';
2
3import { getPlatformBundlers, PlatformBundlers } from '../start/server/platformBundlers';
4import { CommandError } from '../utils/errors';
5
6export type Options = {
7  outputDir: string;
8  platforms: Platform[];
9  maxWorkers?: number;
10  dev: boolean;
11  clear: boolean;
12  dumpAssetmap: boolean;
13  dumpSourcemap: boolean;
14};
15
16/** Returns an array of platforms based on the input platform identifier and runtime constraints. */
17export function resolvePlatformOption(
18  platformBundlers: PlatformBundlers,
19  platform: string = 'all'
20): Platform[] {
21  const platforms: Partial<PlatformBundlers> = Object.fromEntries(
22    Object.entries(platformBundlers).filter(([, bundler]) => bundler === 'metro')
23  );
24
25  if (!Object.keys(platforms).length) {
26    throw new CommandError(
27      `No platforms are configured to use the Metro bundler in the project Expo config.`
28    );
29  }
30
31  const assertPlatformBundler = (platform: Platform) => {
32    if (!platforms[platform]) {
33      throw new CommandError(
34        'BAD_ARGS',
35        `Platform "${platform}" is not configured to use the Metro bundler in the project Expo config.`
36      );
37    }
38  };
39
40  switch (platform) {
41    case 'ios':
42      assertPlatformBundler('ios');
43      return ['ios'];
44    case 'web':
45      assertPlatformBundler('web');
46      return ['web'];
47    case 'android':
48      assertPlatformBundler('android');
49      return ['android'];
50    case 'all':
51      return Object.keys(platforms) as Platform[];
52    default:
53      throw new CommandError(
54        `Unsupported platform "${platform}". Options are: ${Object.keys(platforms).join(',')}, all`
55      );
56  }
57}
58
59export async function resolveOptionsAsync(projectRoot: string, args: any): Promise<Options> {
60  const { exp } = getConfig(projectRoot, { skipPlugins: true, skipSDKVersionRequirement: true });
61  const platformBundlers = getPlatformBundlers(exp);
62  const platforms: Platform[] = resolvePlatformOption(
63    platformBundlers,
64    args['--platform'] ?? 'all'
65  );
66
67  return {
68    outputDir: args['--output-dir'] ?? 'dist',
69    platforms,
70    clear: !!args['--clear'],
71    dev: !!args['--dev'],
72    maxWorkers: args['--max-workers'],
73    dumpAssetmap: !!args['--dump-assetmap'],
74    dumpSourcemap: !!args['--dump-sourcemap'],
75  };
76}
77