execute method
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
''');
}