@api-buddy/plugin-utils
Version:
Shared utilities for API Buddy plugins
116 lines (99 loc) • 2.95 kB
text/typescript
import { Command } from 'commander';
// Define a basic Logger interface if @api-buddy/types is not available
interface Logger {
info: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
debug: (message: string) => void;
}
import { BaseCommand, CommandContext } from './commands/base-command.js';
import * as utils from './utils/index.js';
export interface PluginCLIOptions {
name: string;
version: string;
description?: string;
logger?: Logger;
cwd?: string;
}
export class PluginCLI {
private program: Command;
private commandClasses: Map<string, new (context: CommandContext) => BaseCommand> = new Map();
private context: CommandContext;
constructor(options: PluginCLIOptions) {
this.program = new Command();
this.program
.name(options.name)
.version(options.version)
.description(options.description || '');
// Add common options
this.program
.option('--verbose', 'Enable verbose logging', false)
.option('--dry-run', 'Perform a dry run without making changes', false);
this.context = {
cwd: options.cwd || process.cwd(),
logger: {
info: console.log,
warn: console.warn,
error: console.error,
debug: options.logger?.debug || (() => {}),
},
config: {},
data: new Map(),
utils: {
registerHook: () => {},
unregisterHook: () => {},
callHook: async () => undefined,
},
};
}
/**
* Register a command
*/
registerCommand(commandClass: typeof BaseCommand): this {
const command = new commandClass(this.context);
const meta = command.getMetadata();
const cmd = this.program
.command(meta.name)
.description(meta.description || '');
// Register command-specific arguments
meta.arguments?.forEach((arg) => {
cmd.argument(
arg.required ? `<${arg.name}>` : `[${arg.name}]`,
arg.description || ''
);
});
// Register command-specific options
meta.options?.forEach((opt: { flags: string; description?: string; defaultValue?: string | boolean }) => {
cmd.option(
opt.flags,
opt.description || '',
opt.defaultValue
);
});
// Add action to execute the command
cmd.action(async (...args: any[]) => {
try {
const commandInstance = new commandClass(this.context);
await commandInstance.run(process.argv);
} catch (error) {
console.error('Error executing command:', error);
process.exit(1);
}
});
return this;
}
/**
* Parse and execute the CLI
*/
async run(argv: string[] = process.argv): Promise<void> {
await this.program.parseAsync(argv);
}
}
// Export everything
export * from './commands/base-command';
export * from './utils';
// Export a default instance for convenience
export default {
PluginCLI,
...utils,
};