All files / packages/cli/src/commands generate.js

11.71% Statements 15/128
100% Branches 0/0
0% Functions 0/2
11.71% Lines 15/128

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 1611x 1x 1x                       1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                                                                                                                                                                               1x   1x              
/**
 * Generate command - Generates components, pages, and APIs
 */
 
import { Command } from 'commander';
import prompts from 'prompts';
import ora from 'ora';
import picocolors from 'picocolors';
import { existsSync } from 'fs';
import { generateComponent } from '../generators/component-generator.js';
import { generatePage } from '../generators/page-generator.js';
import { generateAPI } from '../generators/api-generator.js';
import { validateComponentName } from '../utils/validation.js';
 
export const generateCommand = new Command('generate')
  .alias('g')
  .description('Generate components, pages, and APIs')
  .argument('[type]', 'type to generate (component, page, api)')
  .argument('[name]', 'name of the item to generate')
  .option('-p, --path <path>', 'custom output path')
  .option('-t, --template <template>', 'template to use')
  .option('--skip-test', 'skip generating test file')
  .option('--skip-story', 'skip generating story file')
  .action(async (type, name, options) => {
    let generationType = type;
    let itemName = name;
 
    // Interactive type selection if not provided
    if (!generationType) {
      const response = await prompts({
        type: 'select',
        name: 'type',
        message: 'What would you like to generate?',
        choices: [
          { title: '🧩 Component', value: 'component', description: 'Reusable UI component' },
          { title: '📄 Page', value: 'page', description: 'Full page with routing' },
          { title: '🔌 API Route', value: 'api', description: 'API endpoint with validation' },
          { title: '📊 Database Model', value: 'model', description: 'Database model with migrations' },
          { title: '🔄 Middleware', value: 'middleware', description: 'Express/Fastify middleware' }
        ]
      });
 
      if (!response.type) {
        console.log(picocolors.yellow('👋 Generation cancelled'));
        process.exit(0);
      }
 
      generationType = response.type;
    }
 
    // Interactive name input if not provided
    if (!itemName) {
      const response = await prompts({
        type: 'text',
        name: 'name',
        message: `What is the ${generationType} name?`,
        validate: validateComponentName
      });
 
      if (!response.name) {
        console.log(picocolors.yellow('👋 Generation cancelled'));
        process.exit(0);
      }
 
      itemName = response.name;
    }
 
    // Validate name
    const nameValidation = validateComponentName(itemName);
    if (nameValidation !== true) {
      console.error(picocolors.red('❌ Invalid name:'), nameValidation);
      process.exit(1);
    }
 
    console.log();
    console.log(picocolors.cyan(`🚀 Generating ${generationType}...`));
    console.log(picocolors.gray('📝 Name:'), picocolors.bold(itemName));
    
    if (options.path) {
      console.log(picocolors.gray('📍 Path:'), options.path);
    }
    
    console.log();
 
    const spinner = ora(`Generating ${generationType}...`).start();
 
    try {
      let result;
 
      switch (generationType) {
        case 'component':
        case 'comp':
        case 'c':
          result = await generateComponent(itemName, options);
          break;
 
        case 'page':
        case 'p':
          result = await generatePage(itemName, options);
          break;
 
        case 'api':
        case 'route':
        case 'r':
          result = await generateAPI(itemName, options);
          break;
 
        case 'model':
        case 'm':
          result = await generateModel(itemName, options);
          break;
 
        case 'middleware':
        case 'mw':
          result = await generateMiddleware(itemName, options);
          break;
 
        default:
          throw new Error(`Unknown generation type: ${generationType}`);
      }
 
      spinner.succeed(`${generationType} generated successfully!`);
 
      // Success message
      console.log();
      console.log(picocolors.green(`✅ ${generationType} generated successfully!`));
      console.log();
      
      // Show generated files
      if (result?.files && result.files.length > 0) {
        console.log(picocolors.cyan('📁 Generated files:'));
        result.files.forEach(file => {
          console.log(picocolors.gray('  ✨'), file);
        });
        console.log();
      }
 
      // Show next steps
      if (result?.nextSteps && result.nextSteps.length > 0) {
        console.log(picocolors.cyan('Next steps:'));
        result.nextSteps.forEach(step => {
          console.log(picocolors.gray('  •'), step);
        });
        console.log();
      }
 
    } catch (error) {
      spinner.fail(`Failed to generate ${generationType}`);
      console.error(picocolors.red('❌ Error:'), error.message);
      process.exit(1);
    }
  });
 
// Placeholder for additional generators
async function generateModel(name, options) {
  throw new Error('Model generation not implemented yet');
}
 
async function generateMiddleware(name, options) {
  throw new Error('Middleware generation not implemented yet');
}