āĻ¸ā§āĻ•āĻŋāĻĒ āĻ•āϰ⧇ āĻŽā§‚āϞ āĻ•āĻ¨ā§āĻŸā§‡āĻ¨ā§āϟ āĻ āϝāĻžāύ

🚀 flx gen feature

flx gen feature āĻšāϞ FLX CLI-āϰ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ powerful command āϝāĻž āĻāĻ•āϟāĻŋ complete Clean Architecture feature structure āϤ⧈āϰāĻŋ āĻ•āϰ⧇āĨ¤

đŸŽ¯ Command Overview​

flx gen feature <feature_name>

📝 Description​

āĻāχ command āĻāĻ•āϟāĻŋ complete feature āϤ⧈āϰāĻŋ āĻ•āϰ⧇ āϝāĻžāϤ⧇ āĻĨāĻžāϕ⧇:

  • Domain Layer: Entities, Use Cases, Repository Interfaces
  • Data Layer: Models, Data Sources, Repository Implementations
  • Presentation Layer: Pages, Controllers/BLoC, Bindings

🎨 Basic Usage​

Simple Feature Generation​

# Authentication feature āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ
flx gen feature auth

# ✅ Output:
# ✅ Generated feature "auth" with files:
# - lib/features/auth/domain/entities/auth_entity.dart
# - lib/features/auth/data/models/auth_model.dart
# - lib/features/auth/data/datasources/auth_remote_data_source.dart
# - lib/features/auth/data/repositories/auth_repository_impl.dart
# - lib/features/auth/domain/repositories/auth_repository.dart
# - lib/features/auth/domain/usecases/auth_usecase.dart
# - lib/features/auth/presentation/pages/auth_page.dart
# - lib/features/auth/presentation/bindings/auth_binding.dart
# - lib/features/auth/presentation/controllers/auth_controller.dart (GetX)
# OR
# - lib/features/auth/presentation/bloc/auth_bloc.dart (BLoC)
# - lib/features/auth/presentation/bloc/auth_event.dart (BLoC)
# - lib/features/auth/presentation/bloc/auth_state.dart (BLoC)

Multiple Features​

# āĻāĻ•āĻžāϧāĻŋāĻ• features āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ
flx gen feature auth
flx gen feature dashboard
flx gen feature profile
flx gen feature settings

# ✅ Result: 4āϟāĻŋ complete features ready!

📁 Generated Structure​

đŸŽ¯ GetX Configuration​

flx config --state getx
flx gen feature auth

Generated Files:

lib/features/auth/
├── data/
│ ├── datasources/
│ │ └── auth_remote_data_source.dart
│ ├── models/
│ │ └── auth_model.dart
│ └── repositories/
│ └── auth_repository_impl.dart
├── domain/
│ ├── entities/
│ │ └── auth_entity.dart
│ ├── repositories/
│ │ └── auth_repository.dart
│ └── usecases/
│ └── auth_usecase.dart
└── presentation/
├── bindings/
│ └── auth_binding.dart
├── controllers/
│ └── auth_controller.dart
└── pages/
└── auth_page.dart

🧱 BLoC Configuration​

flx config --state bloc
flx gen feature auth

Generated Files:

lib/features/auth/
├── data/
│ └── ... (same as GetX)
├── domain/
│ └── ... (same as GetX)
└── presentation/
├── bindings/
│ └── auth_binding.dart
├── bloc/
│ ├── auth_bloc.dart
│ ├── auth_event.dart
│ └── auth_state.dart
└── pages/
└── auth_page.dart

🔍 Generated Code Examples​

1. 🏷 Domain Entity​

File: lib/features/auth/domain/entities/auth_entity.dart

import 'package:freezed_annotation/freezed_annotation.dart';

part 'auth_entity.freezed.dart';


class AuthEntity with _$AuthEntity {
const factory AuthEntity({
required String id,
// Add your entity properties here
}) = _AuthEntity;
}

2. 📋 Repository Interface​

File: lib/features/auth/domain/repositories/auth_repository.dart

import '../entities/auth_entity.dart';

abstract class AuthRepository {
Future<List<AuthEntity>> getAll();
Future<AuthEntity?> getById(String id);
Future<AuthEntity> create(AuthEntity entity);
Future<AuthEntity> update(AuthEntity entity);
Future<void> delete(String id);
}

3. đŸŽ¯ Use Case​

File: lib/features/auth/domain/usecases/auth_usecase.dart

import '../entities/auth_entity.dart';
import '../repositories/auth_repository.dart';

class AuthUseCase {
const AuthUseCase(this._repository);

final AuthRepository _repository;

Future<List<AuthEntity>> call() async {
return await _repository.getAll();
}
}

4. 🏗 Data Model​

File: lib/features/auth/data/models/auth_model.dart

import 'package:freezed_annotation/freezed_annotation.dart';
import '../../domain/entities/auth_entity.dart';

part 'auth_model.freezed.dart';
part 'auth_model.g.dart';


class AuthModel with _$AuthModel {
const factory AuthModel({
required String id,
// Add your model properties here
}) = _AuthModel;

factory AuthModel.fromJson(Map<String, dynamic> json) =>
_$AuthModelFromJson(json);
}

extension AuthModelX on AuthModel {
AuthEntity toEntity() {
return AuthEntity(
id: id,
// Map your properties here
);
}
}

5. 🌐 Data Source​

File: lib/features/auth/data/datasources/auth_remote_data_source.dart

import '../models/auth_model.dart';

abstract class AuthRemoteDataSource {
Future<List<AuthModel>> getAll();
Future<AuthModel?> getById(String id);
Future<AuthModel> create(AuthModel model);
Future<AuthModel> update(AuthModel model);
Future<void> delete(String id);
}

class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
const AuthRemoteDataSourceImpl();


Future<List<AuthModel>> getAll() async {
// TODO: Implement API call
throw UnimplementedError('getAll() not implemented');
}


Future<AuthModel?> getById(String id) async {
// TODO: Implement API call
throw UnimplementedError('getById() not implemented');
}

// ... other methods
}

6. 🔄 Repository Implementation​

File: lib/features/auth/data/repositories/auth_repository_impl.dart

import '../../domain/entities/auth_entity.dart';
import '../../domain/repositories/auth_repository.dart';
import '../datasources/auth_remote_data_source.dart';
import '../models/auth_model.dart';

class AuthRepositoryImpl implements AuthRepository {
const AuthRepositoryImpl(this._remoteDataSource);

final AuthRemoteDataSource _remoteDataSource;


Future<List<AuthEntity>> getAll() async {
final models = await _remoteDataSource.getAll();
return models.map((model) => model.toEntity()).toList();
}


Future<AuthEntity?> getById(String id) async {
final model = await _remoteDataSource.getById(id);
return model?.toEntity();
}

// ... other methods
}

7. 🎮 GetX Controller​

File: lib/features/auth/presentation/controllers/auth_controller.dart

import 'package:get/get.dart';
import '../../domain/entities/auth_entity.dart';
import '../../domain/usecases/auth_usecase.dart';

class AuthController extends GetxController {
AuthController(this._authUseCase);

final AuthUseCase _authUseCase;

final _isLoading = false.obs;
final _authList = <AuthEntity>[].obs;

bool get isLoading => _isLoading.value;
List<AuthEntity> get authList => _authList;


void onInit() {
super.onInit();
loadAuths();
}

Future<void> loadAuths() async {
try {
_isLoading.value = true;
final result = await _authUseCase();
_authList.value = result;
} catch (e) {
Get.snackbar('Error', 'Failed to load auths: $e');
} finally {
_isLoading.value = false;
}
}

Future<void> refresh() async {
await loadAuths();
}
}

8. 🧱 BLoC Files​

auth_bloc.dart:

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import '../../domain/entities/auth_entity.dart';
import '../../domain/usecases/auth_usecase.dart';

part 'auth_event.dart';
part 'auth_state.dart';

class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc(this._authUseCase) : super(AuthInitial()) {
on<LoadAuths>(_onLoadAuths);
on<RefreshAuths>(_onRefreshAuths);
}

final AuthUseCase _authUseCase;

Future<void> _onLoadAuths(
LoadAuths event,
Emitter<AuthState> emit,
) async {
emit(AuthLoading());
try {
final result = await _authUseCase();
emit(AuthLoaded(result));
} catch (e) {
emit(AuthError(e.toString()));
}
}

// ... other event handlers
}

auth_event.dart:

part of 'auth_bloc.dart';

abstract class AuthEvent extends Equatable {
const AuthEvent();


List<Object> get props => [];
}

class LoadAuths extends AuthEvent {
const LoadAuths();
}

class RefreshAuths extends AuthEvent {
const RefreshAuths();
}

auth_state.dart:

part of 'auth_bloc.dart';

abstract class AuthState extends Equatable {
const AuthState();


List<Object> get props => [];
}

class AuthInitial extends AuthState {
const AuthInitial();
}

class AuthLoading extends AuthState {
const AuthLoading();
}

class AuthLoaded extends AuthState {
const AuthLoaded(this.authList);

final List<AuthEntity> authList;


List<Object> get props => [authList];
}

class AuthError extends AuthState {
const AuthError(this.message);

final String message;


List<Object> get props => [message];
}

9. 📱 UI Page​

File: lib/features/auth/presentation/pages/auth_page.dart

GetX Version:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/auth_controller.dart';

class AuthPage extends GetView<AuthController> {
const AuthPage({Key? key}) : super(key: key);


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Auth'),
),
body: Obx(() {
if (controller.isLoading) {
return const Center(child: CircularProgressIndicator());
}

return RefreshIndicator(
onRefresh: controller.refresh,
child: ListView.builder(
itemCount: controller.authList.length,
itemBuilder: (context, index) {
final item = controller.authList[index];
return ListTile(
title: Text(item.id),
// Add more UI components here
);
},
),
);
}),
);
}
}

BLoC Version:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../bloc/auth_bloc.dart';

class AuthPage extends StatelessWidget {
const AuthPage({Key? key}) : super(key: key);


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Auth'),
),
body: BlocBuilder<AuthBloc, AuthState>(
builder: (context, state) {
if (state is AuthLoading) {
return const Center(child: CircularProgressIndicator());
}

if (state is AuthError) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Error: ${state.message}'),
ElevatedButton(
onPressed: () => context.read<AuthBloc>().add(const RefreshAuths()),
child: const Text('Retry'),
),
],
),
);
}

if (state is AuthLoaded) {
return RefreshIndicator(
onRefresh: () async {
context.read<AuthBloc>().add(const RefreshAuths());
},
child: ListView.builder(
itemCount: state.authList.length,
itemBuilder: (context, index) {
final item = state.authList[index];
return ListTile(
title: Text(item.id),
// Add more UI components here
);
},
),
);
}

return const Center(child: Text('No data available'));
},
),
);
}
}

10. 🔗 Dependency Injection​

GetX Binding:

import 'package:get/get.dart';
import '../../data/datasources/auth_remote_data_source.dart';
import '../../data/repositories/auth_repository_impl.dart';
import '../../domain/repositories/auth_repository.dart';
import '../../domain/usecases/auth_usecase.dart';
import '../controllers/auth_controller.dart';

class AuthBinding extends Bindings {

void dependencies() {
Get.lazyPut<AuthRemoteDataSource>(
() => AuthRemoteDataSourceImpl(),
);

Get.lazyPut<AuthRepository>(
() => AuthRepositoryImpl(Get.find()),
);

Get.lazyPut<AuthUseCase>(
() => AuthUseCase(Get.find()),
);

Get.lazyPut<AuthController>(
() => AuthController(Get.find()),
);
}
}

BLoC Provider:

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import '../../data/datasources/auth_remote_data_source.dart';
import '../../data/repositories/auth_repository_impl.dart';
import '../../domain/repositories/auth_repository.dart';
import '../../domain/usecases/auth_usecase.dart';
import '../bloc/auth_bloc.dart';

class AuthProvider {
static void init() {
final getIt = GetIt.instance;

// Data Sources
getIt.registerLazySingleton<AuthRemoteDataSource>(
() => AuthRemoteDataSourceImpl(),
);

// Repositories
getIt.registerLazySingleton<AuthRepository>(
() => AuthRepositoryImpl(getIt()),
);

// Use Cases
getIt.registerLazySingleton<AuthUseCase>(
() => AuthUseCase(getIt()),
);

// BLoC
getIt.registerFactory<AuthBloc>(
() => AuthBloc(getIt()),
);
}

static BlocProvider<AuthBloc> provide({
required Widget child,
}) {
return BlocProvider<AuthBloc>(
create: (context) => GetIt.instance<AuthBloc>()..add(const LoadAuths()),
child: child,
);
}
}

đŸŽ¯ Naming Conventions​

Feature Names​

# ✅ Good names (snake_case)
flx gen feature user_profile
flx gen feature order_management
flx gen feature payment_gateway

# ❌ Avoid these
flx gen feature UserProfile # PascalCase
flx gen feature user-profile # kebab-case
flx gen feature userProfile # camelCase

Generated Class Names​

// Feature: user_profile
UserProfileEntity // Entity
UserProfileModel // Model
UserProfileUseCase // Use Case
UserProfileController // Controller
UserProfileBloc // BLoC
UserProfilePage // Page

🚀 Real-World Examples​

E-commerce Features​

# Core features
flx gen feature auth
flx gen feature product_catalog
flx gen feature shopping_cart
flx gen feature order_management
flx gen feature payment_processing
flx gen feature user_profile

# Admin features
flx gen feature admin_dashboard
flx gen feature inventory_management
flx gen feature customer_support

Social Media Features​

# User features
flx gen feature user_registration
flx gen feature user_profile
flx gen feature friend_management
flx gen feature post_creation
flx gen feature news_feed
flx gen feature messaging
flx gen feature notifications

🔄 Next Steps​

After Generation​

  1. Customize Entities: Add your specific properties
  2. Implement Data Sources: Add actual API calls
  3. Update Use Cases: Add business logic
  4. Style UI Pages: Design your user interface
  5. Add Navigation: Connect pages with routing

Example Customization​

// Customize auth_entity.dart

class AuthEntity with _$AuthEntity {
const factory AuthEntity({
required String id,
required String email,
required String name,
required String token,
required DateTime createdAt,
required bool isVerified,
}) = _AuthEntity;
}

// Update auth_model.dart accordingly
// Implement actual API calls in auth_remote_data_source.dart
// Add business validation in auth_usecase.dart

📋 Best Practices​

✅ DO​

  1. Feature Planning: Generate āĻ•āϰāĻžāϰ āφāϗ⧇ feature requirements clear āĻ•āϰ⧁āύ
  2. Consistent Naming: snake_case āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ
  3. Immediate Customization: Generate āĻ•āϰāĻžāϰ āĻĒāϰ immediately customize āĻ•āϰ⧁āύ
  4. Version Control: Generated files commit āĻ•āϰ⧁āύ

❌ DON'T​

  1. Mixed Naming: Different naming conventions mix āĻ•āϰāĻŦ⧇āύ āύāĻž
  2. Mass Generation: āϏāĻŦ features āĻāĻ•āϏāĻžāĻĨ⧇ generate āĻ•āϰ⧇ customize āύāĻž āĻ•āϰāĻž
  3. Template Dependency: Generated templates-āĻāϰ āωāĻĒāϰ completely āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰāĻž

Ready to create your first feature? 🚀 Installation complete āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ flx gen feature auth āĻĻāĻŋāϝāĻŧ⧇ āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ!