18d307f52SEvan Baconimport { ModPlatform } from '@expo/config-plugins';
28d307f52SEvan Baconimport assert from 'assert';
38d307f52SEvan Baconimport chalk from 'chalk';
48d307f52SEvan Baconimport fs from 'fs';
58d307f52SEvan Baconimport path from 'path';
68d307f52SEvan Bacon
78d307f52SEvan Baconimport * as Log from '../log';
88d307f52SEvan Baconimport { CommandError } from '../utils/errors';
98d307f52SEvan Baconimport { validateUrl } from '../utils/url';
108d307f52SEvan Bacon
116caf5755SEvan Baconexport function resolvePackageManagerOptions(args: any) {
126caf5755SEvan Bacon  const managers: Record<string, boolean> = {
136caf5755SEvan Bacon    npm: args['--npm'],
146caf5755SEvan Bacon    yarn: args['--yarn'],
156caf5755SEvan Bacon    pnpm: args['--pnpm'],
16*9b1b5ec6SEvan Bacon    bun: args['--bun'],
176caf5755SEvan Bacon  };
186caf5755SEvan Bacon
196caf5755SEvan Bacon  if (
20*9b1b5ec6SEvan Bacon    [managers.npm, managers.pnpm, managers.yarn, managers.bun, !!args['--no-install']].filter(
21*9b1b5ec6SEvan Bacon      Boolean
22*9b1b5ec6SEvan Bacon    ).length > 1
236caf5755SEvan Bacon  ) {
246caf5755SEvan Bacon    throw new CommandError(
256caf5755SEvan Bacon      'BAD_ARGS',
26*9b1b5ec6SEvan Bacon      'Specify at most one of: --no-install, --npm, --pnpm, --yarn, --bun'
276caf5755SEvan Bacon    );
286caf5755SEvan Bacon  }
296caf5755SEvan Bacon
306caf5755SEvan Bacon  return managers;
316caf5755SEvan Bacon}
326caf5755SEvan Bacon
338d307f52SEvan Bacon/** Resolves a template option as a URL or file path pointing to a tar file. */
348d307f52SEvan Baconexport function resolveTemplateOption(template: string) {
358d307f52SEvan Bacon  if (validateUrl(template)) {
368d307f52SEvan Bacon    return template;
378d307f52SEvan Bacon  }
388d307f52SEvan Bacon  const templatePath = path.resolve(template);
398d307f52SEvan Bacon  assert(fs.existsSync(templatePath), 'template file does not exist: ' + templatePath);
408d307f52SEvan Bacon  assert(
418d307f52SEvan Bacon    fs.statSync(templatePath).isFile(),
428d307f52SEvan Bacon    'template must be a tar file created by running `npm pack` in a project: ' + templatePath
438d307f52SEvan Bacon  );
448d307f52SEvan Bacon
458d307f52SEvan Bacon  return templatePath;
468d307f52SEvan Bacon}
478d307f52SEvan Bacon
488d307f52SEvan Bacon/** Resolves dependencies to skip from a string joined by `,`. Example: `react-native,expo,lodash` */
498d307f52SEvan Baconexport function resolveSkipDependencyUpdate(value: any) {
508d307f52SEvan Bacon  if (!value || typeof value !== 'string') {
518d307f52SEvan Bacon    return [];
528d307f52SEvan Bacon  }
538d307f52SEvan Bacon  return value.split(',');
548d307f52SEvan Bacon}
558d307f52SEvan Bacon
568d307f52SEvan Bacon/** Returns an array of platforms based on the input platform identifier and runtime constraints. */
578d307f52SEvan Baconexport function resolvePlatformOption(
588d307f52SEvan Bacon  platform: string = 'all',
598d307f52SEvan Bacon  { loose }: { loose?: boolean } = {}
608d307f52SEvan Bacon): ModPlatform[] {
618d307f52SEvan Bacon  switch (platform) {
628d307f52SEvan Bacon    case 'ios':
638d307f52SEvan Bacon      return ['ios'];
648d307f52SEvan Bacon    case 'android':
658d307f52SEvan Bacon      return ['android'];
668d307f52SEvan Bacon    case 'all':
675492d26aSCedric van Putten      return loose || process.platform !== 'win32' ? ['android', 'ios'] : ['android'];
688d307f52SEvan Bacon    default:
695492d26aSCedric van Putten      return [platform as ModPlatform];
708d307f52SEvan Bacon  }
718d307f52SEvan Bacon}
728d307f52SEvan Bacon
738d307f52SEvan Bacon/** Warns and filters out unsupported platforms based on the runtime constraints. Essentially this means no iOS on Windows devices. */
748d307f52SEvan Baconexport function ensureValidPlatforms(platforms: ModPlatform[]): ModPlatform[] {
758d307f52SEvan Bacon  // Skip ejecting for iOS on Windows
768d307f52SEvan Bacon  if (process.platform === 'win32' && platforms.includes('ios')) {
778d307f52SEvan Bacon    Log.warn(
788d307f52SEvan Bacon      chalk`⚠️  Skipping generating the iOS native project files. Run {bold expo eject} again from macOS or Linux to generate the iOS project.\n`
798d307f52SEvan Bacon    );
808d307f52SEvan Bacon    return platforms.filter((platform) => platform !== 'ios');
818d307f52SEvan Bacon  }
828d307f52SEvan Bacon  return platforms;
838d307f52SEvan Bacon}
848d307f52SEvan Bacon
858d307f52SEvan Bacon/** Asserts platform length must be greater than zero. */
868d307f52SEvan Baconexport function assertPlatforms(platforms: ModPlatform[]) {
878d307f52SEvan Bacon  if (!platforms?.length) {
888d307f52SEvan Bacon    throw new CommandError('At least one platform must be enabled when syncing');
898d307f52SEvan Bacon  }
908d307f52SEvan Bacon}
91