execute method

Future<void> execute()

Implementation

Future<void> execute() async {
  final snakeName = StringUtils.toSnakeCase(featureName);
  final pascalName = StringUtils.toPascalCase(featureName);
  final camelName = StringUtils.toCamelCase(featureName);

  // Check if running from project root
  final currentDir = Directory.current.path;
  final melosFile = File('$currentDir/melos.yaml');
  final packagesDir = Directory('$currentDir/packages');

  if (!melosFile.existsSync() || !packagesDir.existsSync()) {
    Logger.error(
        '❌ Please run this command from the project root directory!');
    Logger.error(
        '   (The directory containing melos.yaml and packages/ folder)');
    print('');
    print('Current directory: $_cyan$currentDir$_reset');
    print('Expected files: ${_cyan}melos.yaml, packages/$_reset');
    exit(1);
  }

  Logger.header('Creating Feature: $snakeName');

  // Determine packages path
  final packagesPath =
      currentDir.endsWith('packages') ? currentDir : '$currentDir/packages';

  final featurePath = '$packagesPath/features_$snakeName';

  // Check if feature already exists
  if (Directory(featurePath).existsSync()) {
    Logger.error('Feature "features_$snakeName" already exists!');
    exit(1);
  }

  // Create directory structure
  Logger.step('Creating directory structure...');
  _createDirectoryStructure(featurePath);
  Logger.success('Directory structure created');

  // Generate files
  Logger.step('Generating files...');

  // pubspec.yaml
  final pubspecContent = PubspecGenerator.generate(snakeName);
  _writeFile('$featurePath/pubspec.yaml', pubspecContent);
  Logger.success('Generated pubspec.yaml');

  // Barrel export
  final barrelContent = BarrelExportGenerator.generate(snakeName);
  _writeFile('$featurePath/lib/features_$snakeName.dart', barrelContent);
  Logger.success('Generated barrel export file');

  // Domain layer
  final entityContent = EntityGenerator.generate(snakeName, pascalName);
  _writeFile('$featurePath/lib/domain/entities/${snakeName}_entity.dart',
      entityContent);
  Logger.success('Generated entity');

  final repositoryContent =
      RepositoryGenerator.generate(snakeName, pascalName);
  _writeFile(
      '$featurePath/lib/domain/repositories/${snakeName}_repository.dart',
      repositoryContent);
  Logger.success('Generated repository interface');

  final usecaseContent =
      UseCaseGenerator.generate(snakeName, pascalName, camelName);
  _writeFile('$featurePath/lib/domain/usecases/get_${snakeName}_usecase.dart',
      usecaseContent);
  Logger.success('Generated use cases');

  // Data layer
  final modelContent = ModelGenerator.generate(snakeName, pascalName);
  _writeFile(
      '$featurePath/lib/data/models/${snakeName}_model.dart', modelContent);
  Logger.success('Generated model');

  final datasourceContent =
      DataSourceGenerator.generate(snakeName, pascalName);
  _writeFile(
      '$featurePath/lib/data/datasources/${snakeName}_remote_datasource.dart',
      datasourceContent);
  Logger.success('Generated remote datasource');

  final repoImplContent =
      RepositoryImplGenerator.generate(snakeName, pascalName, camelName);
  _writeFile(
      '$featurePath/lib/data/repositories/${snakeName}_repository_impl.dart',
      repoImplContent);
  Logger.success('Generated repository implementation');

  // Presentation layer
  final blocFiles = BlocGenerator.generate(snakeName, pascalName, camelName);
  _writeFile('$featurePath/lib/presentation/bloc/${snakeName}_bloc.dart',
      blocFiles['bloc']!);
  _writeFile('$featurePath/lib/presentation/bloc/${snakeName}_event.dart',
      blocFiles['event']!);
  _writeFile('$featurePath/lib/presentation/bloc/${snakeName}_state.dart',
      blocFiles['state']!);
  Logger.success('Generated BLoC files');

  final pageContent =
      PageGenerator.generate(snakeName, pascalName, camelName);
  _writeFile('$featurePath/lib/presentation/pages/${snakeName}_page.dart',
      pageContent);
  Logger.success('Generated page');

  // Create empty widgets folder with .gitkeep
  _writeFile('$featurePath/lib/presentation/widgets/.gitkeep', '');

  // Add route to app_routes.dart
  Logger.step('Adding route to app_routes.dart...');
  _addRouteToAppRoutes(snakeName, camelName, pascalName);
  Logger.success('Route added to app_routes.dart');

  // Register route in app_router.dart (go_router)
  Logger.step('Registering route in app_router.dart...');
  _registerRouteInAppRouter(snakeName, pascalName, camelName);
  Logger.success('Route registered in app_router.dart');

  // Add to app/pubspec.yaml
  Logger.step('Adding dependency to app/pubspec.yaml...');
  _addToAppPubspec(snakeName);
  Logger.success('Dependency added to app/pubspec.yaml');

  // Install dependencies
  Logger.step('Installing dependencies...');
  _installDependencies(featurePath);
  Logger.success('Dependencies installed');

  Logger.header('Feature Created Successfully! 🎉');

  print('''
Next steps:

1. Register in app/lib/injection_container.dart:
 $_cyan// Data Sources
 getIt.registerLazySingleton<${pascalName}RemoteDataSource>(
   () => ${pascalName}RemoteDataSource(getIt<DioClient>()),
 );

 // Repositories
 getIt.registerLazySingleton<${pascalName}Repository>(
   () => ${pascalName}RepositoryImpl(getIt<${pascalName}RemoteDataSource>()),
 );

 // Use Cases
 getIt.registerLazySingleton<Get${pascalName}UseCase>(
   () => Get${pascalName}UseCase(getIt<${pascalName}Repository>()),
 );

 // BLoC
 getIt.registerFactory<${pascalName}Bloc>(
   () => ${pascalName}Bloc(getIt<Get${pascalName}UseCase>()),
 );$_reset

$_green✨ What was done automatically:$_reset
 • Created complete Clean Architecture structure
 • Added dependency to app/pubspec.yaml
 • Installed all feature dependencies
 • Registered routes in app_routes.dart
 • Registered GoRoute in app_router.dart

Feature location: $_green$featurePath$_reset
''');
}