UNPKG

easy-cli-framework

Version:

A framework for building CLI applications that are robust and easy to maintain. Supports theming, configuration files, interactive prompts, and more.

137 lines (123 loc) 4.42 kB
import { CommandSetupOptions, EasyCLICommand } from './command'; import { EasyCLIConfigFile } from '../config-files'; import { EasyCLITheme } from '../themes'; /** * Options for the init command * @interface InitCommandOptions * * @template TGlobalParams The global params for the CLI * @template TParams The params for the command * * @property {boolean} failOnExists Should the command fail if the config file already exists? * @property {(keyof TGlobalParams)[]} globalKeysToUse Any global keys that should be stored in the config file * @property {(keyof TGlobalParams)[]} globalKeysToPrompt Any global keys that should be prompted for. * @property {Partial<TGlobalParams & TParams>} defaults The default values to use * @property {(params: TGlobalParams & TParams) => any} transformer How to transform the params before saving * @property {string} configFlag The name of the variable to use for the config file * * @extends CommandSetupOptions * * @example * ```typescript * { * failOnExists?: boolean; // Should the command fail if the config file already exists? * globalKeysToUse?: string[]; // What key(s) are you setting? * defaults?: Partial<TGlobalParams & TParams>; // The default values to use * configFlag?: string; // The name of the variable to use for the config file * } * ``` */ export type InitCommandOptions<TGlobalParams, TParams> = CommandSetupOptions< TGlobalParams, TParams > & { failOnExists?: boolean; // Should the command fail if the config file already exists? globalKeysToUse?: (keyof TGlobalParams)[]; // What key(s) are you setting? defaults?: Partial<TGlobalParams & TParams>; // The default values to use configFlag?: string; // The name of the variable to use for the config file callback?: (params: TGlobalParams & TParams) => void; // The callback to run after the command is executed, this is useful if you want to add additional functionality to the command ie. Copying a file }; /** * A command to add an init command to the CLI that will save the configuration * * @template TParams The params for the command * @template TGlobalParams The global params for the CLI * * @extends EasyCLICommand * * @example * ```typescript * new EasyCLIInitCommand(config, 'init', { * globalKeysToUse: ['verbose'], * prompts: { * env: { * describe: 'What environent are you setting?', * type: 'string', * prompt: 'always', * demandOption: true, * }, * }, * }); * ``` */ export class EasyCLIInitCommand< TParams extends Record<string, any> = Record<string, any>, TGlobalParams extends Record<string, any> = Record<string, any> > extends EasyCLICommand<TParams, TGlobalParams> { /** * Creates a new init command * @param {EasyCLIConfigFile} config The configuration file to use to save the config * @param {string} [name='init'] The name of the command * @param {InitCommandOptions<TGlobalParams, TParams>} [options={}] The options for the command */ constructor( config: EasyCLIConfigFile, name: string = 'init', options: InitCommandOptions<TGlobalParams, TParams> = {} ) { if (!config) { throw new Error('EasyCLIConfigFile is required for init command'); } const { globalKeysToUse = [], defaults = {}, configFlag = 'config', callback, ...commandOptions } = options; const handler = async ( params: TGlobalParams & TParams, theme?: EasyCLITheme ) => { const logger = theme?.getLogger(); const keys = [...this.getKeys(), ...globalKeysToUse]; const clean = Object.entries(params as any).reduce( (acc, [key, value]) => { if (keys.includes(key as string)) { acc[key] = value; } return acc; }, defaults as any ); logger?.success('Saving config file'); await config.save(clean); if (callback) { await callback(params); } }; const validator = async (params: TGlobalParams & TParams) => { if ( options.failOnExists && config.fileExists((params as any)?.[configFlag] ?? null) ) { throw new Error('Config file already exists'); } if (commandOptions.validator) { return commandOptions.validator(params); } return true; }; super(name, handler, { ...commandOptions, validator }); } }