xref: /expo/packages/@expo/cli/bin/cli.ts (revision c8dced1f)
1#!/usr/bin/env node
2import arg from 'arg';
3import chalk from 'chalk';
4
5const defaultCmd = 'start';
6
7export type Command = (argv?: string[]) => void;
8
9const commands: { [command: string]: () => Promise<Command> } = {
10  // Add a new command here
11  'run:android': () => import('../src/run/android').then((i) => i.expoRunAndroid),
12  start: () => import('../src/start').then((i) => i.expoStart),
13  prebuild: () => import('../src/prebuild').then((i) => i.expoPrebuild),
14  config: () => import('../src/config').then((i) => i.expoConfig),
15  export: () => import('../src/export').then((i) => i.expoExport),
16
17  // Auxiliary commands
18  install: () => import('../src/install').then((i) => i.expoInstall),
19
20  // Auth
21  login: () => import('../src/login').then((i) => i.expoLogin),
22  logout: () => import('../src/logout').then((i) => i.expoLogout),
23  register: () => import('../src/register').then((i) => i.expoRegister),
24  whoami: () => import('../src/whoami').then((i) => i.expoWhoami),
25};
26
27const args = arg(
28  {
29    // Types
30    '--version': Boolean,
31    '--help': Boolean,
32
33    // Aliases
34    '-v': '--version',
35    '-h': '--help',
36  },
37  {
38    permissive: true,
39  }
40);
41
42if (args['--version']) {
43  // Version is added in the build script.
44  console.log(process.env.__EXPO_VERSION);
45  process.exit(0);
46}
47
48// Check if we are running `npx expo <subcommand>` or `npx expo`
49const isSubcommand = Boolean(commands[args._[0]]);
50
51// Handle `--help` flag
52if (!isSubcommand && args['--help']) {
53  const {
54    login,
55    logout,
56    whoami,
57    register,
58    start,
59    install,
60    export: _export,
61    config,
62    prebuild,
63    'run:android': runAndroid,
64    ...others
65  } = commands;
66
67  console.log(chalk`
68  {bold Usage}
69    {dim $} npx expo <command>
70
71  {bold Commands}
72    ${Object.keys({ start, install, export: _export, config, ...others }).join(', ')}
73    ${Object.keys({ 'run:android': runAndroid, prebuild }).join(', ')}
74    {dim ${Object.keys({ login, logout, whoami, register }).join(', ')}}
75
76  {bold Options}
77    --version, -v   Version number
78    --help, -h      Usage info
79
80  For more info run a command with the {bold --help} flag
81    {dim $} npx expo start --help
82`);
83  process.exit(0);
84}
85
86const command = isSubcommand ? args._[0] : defaultCmd;
87const commandArgs = isSubcommand ? args._.slice(1) : args._;
88
89// Push the help flag to the subcommand args.
90if (args['--help']) {
91  commandArgs.push('--help');
92}
93
94// Install exit hooks
95process.on('SIGINT', () => process.exit(0));
96process.on('SIGTERM', () => process.exit(0));
97
98commands[command]().then((exec) => exec(commandArgs));
99