1import { ModPlatform } from '@expo/config-plugins';
2import assert from 'assert';
3import chalk from 'chalk';
4import fs from 'fs';
5import path from 'path';
6
7import * as Log from '../log';
8import { CommandError } from '../utils/errors';
9import { validateUrl } from '../utils/url';
10
11/** Resolves a template option as a URL or file path pointing to a tar file. */
12export function resolveTemplateOption(template: string) {
13  if (validateUrl(template)) {
14    return template;
15  }
16  const templatePath = path.resolve(template);
17  assert(fs.existsSync(templatePath), 'template file does not exist: ' + templatePath);
18  assert(
19    fs.statSync(templatePath).isFile(),
20    'template must be a tar file created by running `npm pack` in a project: ' + templatePath
21  );
22
23  return templatePath;
24}
25
26/** Resolves dependencies to skip from a string joined by `,`. Example: `react-native,expo,lodash` */
27export function resolveSkipDependencyUpdate(value: any) {
28  if (!value || typeof value !== 'string') {
29    return [];
30  }
31  return value.split(',');
32}
33
34/** Returns an array of platforms based on the input platform identifier and runtime constraints. */
35export function resolvePlatformOption(
36  platform: string = 'all',
37  { loose }: { loose?: boolean } = {}
38): ModPlatform[] {
39  switch (platform) {
40    case 'ios':
41      return ['ios'];
42    case 'android':
43      return ['android'];
44    case 'all':
45      if (loose || process.platform !== 'win32') {
46        return ['android', 'ios'];
47      }
48      return ['android'];
49    default:
50      throw new CommandError(`Unsupported platform "${platform}". Options are: ios, android, all`);
51  }
52}
53
54/** Warns and filters out unsupported platforms based on the runtime constraints. Essentially this means no iOS on Windows devices. */
55export function ensureValidPlatforms(platforms: ModPlatform[]): ModPlatform[] {
56  // Skip ejecting for iOS on Windows
57  if (process.platform === 'win32' && platforms.includes('ios')) {
58    Log.warn(
59      chalk`⚠️  Skipping generating the iOS native project files. Run {bold expo eject} again from macOS or Linux to generate the iOS project.\n`
60    );
61    return platforms.filter((platform) => platform !== 'ios');
62  }
63  return platforms;
64}
65
66/** Asserts platform length must be greater than zero. */
67export function assertPlatforms(platforms: ModPlatform[]) {
68  if (!platforms?.length) {
69    throw new CommandError('At least one platform must be enabled when syncing');
70  }
71}
72