18d307f52SEvan Bacon// Common utilities for interacting with `args` library. 28d307f52SEvan Bacon// These functions should be used by every command. 38d307f52SEvan Baconimport arg from 'arg'; 4*83d464dcSEvan Baconimport chalk from 'chalk'; 58d307f52SEvan Baconimport { existsSync } from 'fs'; 68d307f52SEvan Baconimport { resolve } from 'path'; 78d307f52SEvan Bacon 88d307f52SEvan Baconimport * as Log from '../log'; 98d307f52SEvan Bacon 108d307f52SEvan Bacon/** 118d307f52SEvan Bacon * Parse the first argument as a project directory. 128d307f52SEvan Bacon * 138d307f52SEvan Bacon * @returns valid project directory. 148d307f52SEvan Bacon */ 158d307f52SEvan Baconexport function getProjectRoot(args: arg.Result<arg.Spec>) { 168d307f52SEvan Bacon const projectRoot = resolve(args._[0] || '.'); 178d307f52SEvan Bacon 188d307f52SEvan Bacon if (!existsSync(projectRoot)) { 198d307f52SEvan Bacon Log.exit(`Invalid project root: ${projectRoot}`); 208d307f52SEvan Bacon } 218d307f52SEvan Bacon 228d307f52SEvan Bacon return projectRoot; 238d307f52SEvan Bacon} 248d307f52SEvan Bacon 258d307f52SEvan Bacon/** 268d307f52SEvan Bacon * Parse args and assert unknown options. 278d307f52SEvan Bacon * 288d307f52SEvan Bacon * @param schema the `args` schema for parsing the command line arguments. 298d307f52SEvan Bacon * @param argv extra strings 308d307f52SEvan Bacon * @returns processed args object. 318d307f52SEvan Bacon */ 3229975bfdSEvan Baconexport function assertArgs(schema: arg.Spec, argv?: string[]): arg.Result<arg.Spec> { 3309bb6093SEvan Bacon return assertWithOptionsArgs(schema, { argv }); 3409bb6093SEvan Bacon} 3509bb6093SEvan Bacon 3609bb6093SEvan Baconexport function assertWithOptionsArgs( 3709bb6093SEvan Bacon schema: arg.Spec, 3809bb6093SEvan Bacon options: arg.Options 3909bb6093SEvan Bacon): arg.Result<arg.Spec> { 408d307f52SEvan Bacon try { 4109bb6093SEvan Bacon return arg(schema, options); 4229975bfdSEvan Bacon } catch (error: any) { 438d307f52SEvan Bacon // Ensure unknown options are handled the same way. 448d307f52SEvan Bacon if (error.code === 'ARG_UNKNOWN_OPTION') { 458d307f52SEvan Bacon Log.exit(error.message, 1); 468d307f52SEvan Bacon } 478d307f52SEvan Bacon // Otherwise rethrow the error. 488d307f52SEvan Bacon throw error; 498d307f52SEvan Bacon } 508d307f52SEvan Bacon} 51*83d464dcSEvan Bacon 52*83d464dcSEvan Baconexport function printHelp(info: string, usage: string, options: string, extra: string = ''): never { 53*83d464dcSEvan Bacon Log.exit( 54*83d464dcSEvan Bacon chalk` 55*83d464dcSEvan Bacon {bold Info} 56*83d464dcSEvan Bacon ${info} 57*83d464dcSEvan Bacon 58*83d464dcSEvan Bacon {bold Usage} 59*83d464dcSEvan Bacon {dim $} ${usage} 60*83d464dcSEvan Bacon 61*83d464dcSEvan Bacon {bold Options} 62*83d464dcSEvan Bacon ${options.split('\n').join('\n ')} 63*83d464dcSEvan Bacon` + extra, 64*83d464dcSEvan Bacon 0 65*83d464dcSEvan Bacon ); 66*83d464dcSEvan Bacon} 67