xref: /expo/packages/@expo/cli/src/utils/variadic.ts (revision e0694585)
1dfe12d45SEvan Baconimport { CommandError } from '../utils/errors';
2dfe12d45SEvan Bacon
3474a7a4bSEvan Baconconst debug = require('debug')('expo:utils:variadic') as typeof console.log;
4474a7a4bSEvan Bacon
5dfe12d45SEvan Bacon/** Given a list of CLI args, return a sorted set of args based on categories used in a complex command. */
6dfe12d45SEvan Baconexport function parseVariadicArguments(argv: string[]): {
7dfe12d45SEvan Bacon  variadic: string[];
8dfe12d45SEvan Bacon  extras: string[];
9dfe12d45SEvan Bacon  flags: Record<string, boolean>;
10dfe12d45SEvan Bacon} {
11dfe12d45SEvan Bacon  const variadic: string[] = [];
12dfe12d45SEvan Bacon  const flags: Record<string, boolean> = {};
13dfe12d45SEvan Bacon
14dfe12d45SEvan Bacon  for (const arg of argv) {
15dfe12d45SEvan Bacon    if (!arg.startsWith('-')) {
16dfe12d45SEvan Bacon      variadic.push(arg);
17dfe12d45SEvan Bacon    } else if (arg === '--') {
18dfe12d45SEvan Bacon      break;
19dfe12d45SEvan Bacon    } else {
20dfe12d45SEvan Bacon      flags[arg] = true;
21dfe12d45SEvan Bacon    }
22dfe12d45SEvan Bacon  }
23dfe12d45SEvan Bacon
24dfe12d45SEvan Bacon  // Everything after `--` that is not an option is passed to the underlying install command.
25dfe12d45SEvan Bacon  const extras: string[] = [];
26dfe12d45SEvan Bacon
27dfe12d45SEvan Bacon  const extraOperator = argv.indexOf('--');
28dfe12d45SEvan Bacon  if (extraOperator > -1 && argv.length > extraOperator + 1) {
29dfe12d45SEvan Bacon    const extraArgs = argv.slice(extraOperator + 1);
30dfe12d45SEvan Bacon    if (extraArgs.includes('--')) {
31dfe12d45SEvan Bacon      throw new CommandError('BAD_ARGS', 'Unexpected multiple --');
32dfe12d45SEvan Bacon    }
33dfe12d45SEvan Bacon    extras.push(...extraArgs);
34474a7a4bSEvan Bacon    debug('Extra arguments: ' + extras.join(', '));
35dfe12d45SEvan Bacon  }
36dfe12d45SEvan Bacon
37474a7a4bSEvan Bacon  debug(`Parsed arguments (variadic: %O, flags: %O, extra: %O)`, variadic, flags, extras);
38dfe12d45SEvan Bacon
39dfe12d45SEvan Bacon  return {
40dfe12d45SEvan Bacon    variadic,
41dfe12d45SEvan Bacon    flags,
42dfe12d45SEvan Bacon    extras,
43dfe12d45SEvan Bacon  };
44dfe12d45SEvan Bacon}
45dfe12d45SEvan Bacon
46dfe12d45SEvan Baconexport function assertUnexpectedObjectKeys(keys: string[], obj: Record<string, any>): void {
47dfe12d45SEvan Bacon  const unexpectedKeys = Object.keys(obj).filter((key) => !keys.includes(key));
48dfe12d45SEvan Bacon  if (unexpectedKeys.length > 0) {
49dfe12d45SEvan Bacon    throw new CommandError('BAD_ARGS', `Unexpected: ${unexpectedKeys.join(', ')}`);
50dfe12d45SEvan Bacon  }
51dfe12d45SEvan Bacon}
52*e0694585SCedric van Putten
53*e0694585SCedric van Puttenexport function assertUnexpectedVariadicFlags(
54*e0694585SCedric van Putten  expectedFlags: string[],
55*e0694585SCedric van Putten  { extras, flags, variadic }: ReturnType<typeof parseVariadicArguments>,
56*e0694585SCedric van Putten  prefixCommand = ''
57*e0694585SCedric van Putten) {
58*e0694585SCedric van Putten  const unexpectedFlags = Object.keys(flags).filter((key) => !expectedFlags.includes(key));
59*e0694585SCedric van Putten
60*e0694585SCedric van Putten  if (unexpectedFlags.length > 0) {
61*e0694585SCedric van Putten    const intendedFlags = Object.entries(flags)
62*e0694585SCedric van Putten      .filter(([key]) => expectedFlags.includes(key))
63*e0694585SCedric van Putten      .map(([key]) => key);
64*e0694585SCedric van Putten
65*e0694585SCedric van Putten    const cmd = [
66*e0694585SCedric van Putten      prefixCommand,
67*e0694585SCedric van Putten      ...variadic,
68*e0694585SCedric van Putten      ...intendedFlags,
69*e0694585SCedric van Putten      '--',
70*e0694585SCedric van Putten      ...extras.concat(unexpectedFlags),
71*e0694585SCedric van Putten    ].join(' ');
72*e0694585SCedric van Putten
73*e0694585SCedric van Putten    throw new CommandError(
74*e0694585SCedric van Putten      'BAD_ARGS',
75*e0694585SCedric van Putten      `Unexpected: ${unexpectedFlags.join(', ')}\nDid you mean: ${cmd.trim()}`
76*e0694585SCedric van Putten    );
77*e0694585SCedric van Putten  }
78*e0694585SCedric van Putten}
79