#!/usr/bin/env node
import { Command } from 'commander';
import inquirer from 'inquirer';
import chalk from 'chalk';
import ora from 'ora';
import fs from 'fs-extra';
import path from 'path';
// ============================================
// Setup
// ============================================
const program = new Command();
const version = '1.0.0';
program
.name('my-cli')
.description('A cool CLI tool built with TypeScript')
.version(version);
// ============================================
// Commands
// ============================================
program
.command('init')
.description('Initialize a new project')
.option('-f, --force', 'Overwrite existing files')
.action(async (options) => {
console.log(chalk.blue('🚀 Initializing project...'));
// Interactive prompts
const answers = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: 'What is the name of your project?',
default: 'my-app',
},
{
type: 'list',
name: 'template',
message: 'Which template would you like to use?',
choices: ['React', 'Vue', 'Node.js API'],
},
{
type: 'confirm',
name: 'typescript',
message: 'Use TypeScript?',
default: true,
},
]);
const targetDir = path.resolve(process.cwd(), answers.projectName);
// Check if exists
if (fs.existsSync(targetDir) && !options.force) {
console.error(chalk.red('Error: Directory already exists. Use -f to overwrite.'));
process.exit(1);
}
// Spinner
const spinner = ora('Creating project structure...').start();
try {
await new Promise(resolve => setTimeout(resolve, 1500)); // Simulate work
// In reality: await fs.copy(templateDir, targetDir)
if (options.force) {
spinner.text = 'Overwriting existing files...';
}
spinner.succeed(chalk.green(`Successfully created project ${answers.projectName}!`));
console.log('\nNext steps:');
console.log(` cd ${answers.projectName}`);
console.log(' npm install');
console.log(' npm start\n');
} catch (error) {
spinner.fail('Failed to create project');
console.error(error);
}
});
program
.command('generate <type> [name]')
.description('Generate a new component or file')
.action((type, name) => {
if (!['component', 'hook', 'page'].includes(type)) {
console.error(chalk.red(`Invalid type: ${type}. Must be one of: component, hook, page`));
process.exit(1);
}
if (!name) {
console.error(chalk.red('Name is required'));
process.exit(1);
}
console.log(`Generating ${type}: ${chalk.cyan(name)}`);
// Logic to generate file...
});
// ============================================
// Run
// ============================================
program.parse(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp();
}