UNPKG

@featurevisor/core

Version:

Core package of Featurevisor for Node.js usage

111 lines (90 loc) 2.8 kB
import { ProjectConfig } from "../config"; import { Datasource } from "../datasource"; import { commonPlugins, nonProjectPlugins, projectBasedPlugins } from "./plugins"; export interface ParsedOptions { _: string[]; [key: string]: any; } export interface PluginHandlerOptions { rootDirectoryPath: string; projectConfig: ProjectConfig; datasource: Datasource; parsed: ParsedOptions; } export interface Plugin { command: string; // single word handler: (options: PluginHandlerOptions) => Promise<void | boolean>; examples: { command: string; // full command usage description: string; }[]; } export interface RunnerOptions { rootDirectoryPath: string; // optional because Featurevisor CLI can be used without a project projectConfig?: ProjectConfig; datasource?: Datasource; } export async function runCLI(runnerOptions: RunnerOptions) { const yargs = require("yargs"); let y = yargs(process.argv.slice(2)).usage("Usage: <command> [options]"); const registeredSubcommands: string[] = []; const { rootDirectoryPath, projectConfig, datasource } = runnerOptions; function registerPlugin(plugin: Plugin) { const subcommand = plugin.command.split(" ")[0]; if (registeredSubcommands.includes(subcommand)) { console.warn(`Plugin "${subcommand}" already registered. Skipping.`); return; } y = y.command({ command: plugin.command, handler: async function (parsed: ParsedOptions) { // @NOTE: in future, allow yargs options to be defined via plugins if (parsed.schemaVersion && typeof parsed.schemaVersion !== "string") { parsed.schemaVersion = parsed.schemaVersion.toString(); } try { const result = await plugin.handler({ rootDirectoryPath, projectConfig, datasource, parsed, } as PluginHandlerOptions); if (result === false) { process.exit(1); } } catch (error) { console.error(error); process.exit(1); } }, }); for (const example of plugin.examples) { y = y.example(`$0 ${example.command}`, example.description); } registeredSubcommands.push(subcommand); } // non project-based plugins if (!projectConfig) { for (const plugin of nonProjectPlugins) { registerPlugin(plugin); } } // project-based plugins if (projectConfig) { for (const plugin of [...projectBasedPlugins, ...(projectConfig.plugins || [])]) { registerPlugin(plugin); } } // common plugins for (const plugin of commonPlugins) { registerPlugin(plugin); } // show help if no command is provided y.command({ command: "*", handler() { y.showHelp(); }, }).argv; }