Here's the perfect professional README that clearly shows it's a CLI tool and uses generic examples:
# Auto Use Case Generator π
[](https://pub.dev/packages/auto_use_case)
[](https://opensource.org/licenses/MIT)
[](https://github.com/yourusername/auto_use_case/actions)
[](https://dart.dev/effective-dart)
**A CLI tool that automatically generates Clean Architecture use cases from your repository interfaces. Save hours of manual coding!**
---
## β‘ What is This?
### **A Command Line Interface (CLI) Tool** π§
This is **not** a library you import in your code. It's a **command-line tool** that runs in your terminal:
```bash
# Install the CLI tool globally
dart pub global activate auto_use_case
# Use it from any terminal
auto_use_case -r lib/repository.dart -p lib/usecases// You manually create each use case...
class GetUserUseCase {
final UserRepository repository;
GetUserUseCase(this.repository);
Future<User> call(int id) {
return repository.getUser(id);
}
}
// Repeat for each repository method... π«auto_use_case -r lib/repository.dart -p lib/usecasesβ
Generates all use cases automatically
β
Zero copy-paste errors
β
Follows your project structure
β
Works with Either/Failure pattern
# Install globally (like npm install -g)
dart pub global activate auto_use_case# Check it works
auto_use_case --version
# Shows: auto_use_case 1.4.0
# See all commands
auto_use_case --help# Example: Generate use cases for auth repository
auto_use_case \
-r lib/features/auth/repositories/auth_repository.dart \
-p lib/features/auth/domain/usecases
# Check the generated files
ls lib/features/auth/domain/usecases/
# get_user_use_case.dart
# update_user_use_case.dart
# delete_user_use_case.dart
# ...and more!// user_repository.dart
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:myapp/core/errors/failures.dart';
import 'package:myapp/core/usecases/usecase.dart';
class UserRepository {
Future<Either<Failure, User>> getUser(int id);
Future<Either<Failure, List<User>>> getAllUsers();
Future<Either<Failure, void>> deleteUser(String userId);
}// get_user_use_case.dart
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:myapp/core/errors/failures.dart';
import 'package:myapp/core/usecases/usecase.dart';
import 'package:myapp/features/auth/domain/repositories/user_repository.dart';
class GetUserUseCase extends UseCase<User, GetUserUseCaseParams> {
final UserRepository repository;
GetUserUseCase(this.repository);
@override
Future<Either<Failure, User>> call(GetUserUseCaseParams params) {
return repository.getUser(params.id);
}
}
class GetUserUseCaseParams extends Equatable {
final int id;
const GetUserUseCaseParams(this.id);
@override
List<Object?> get props => [id];
}β
Imports preserved - dartz, equatable, your failures.dart and usecase.dart
β
Project structure maintained - Uses your package name from pubspec.yaml
β
Params classes (in Pro mode) for clean parameter handling
β
Error handling - Works with Either<Failure, T> pattern
# Install as global command-line tool
dart pub global activate auto_use_case
# Now use 'auto_use_case' anywhere:
auto_use_case -r lib/repo.dart -p lib/usecasesPerfect for: Daily development, quick generation
# Add to your pubspec.yaml
dev_dependencies:
auto_use_case: ^1.4.0# Use within project
dart run auto_use_case -r lib/repo.dart -p lib/usecasesPerfect for: CI/CD pipelines, team projects with version locking
// product_repository.dart
class ProductRepository {
Future<Product> getProduct(String id);
Future<List<Product>> getAllProducts();
Future<void> updateProduct(Product product);
}Command:
auto_use_case -r lib/repositories/product_repository.dart -p lib/domain/usecases// order_repository.dart
import 'package:dartz/dartz.dart';
import 'package:myapp/core/errors/failures.dart';
class OrderRepository {
Future<Either<Failure, Order>> getOrder(String orderId);
Future<Either<Failure, List<Order>>> getOrdersByUser(String userId);
Future<Either<Failure, void>> cancelOrder(String orderId);
}Command (Pro Mode):
auto_use_case -r lib/repositories/order_repository.dart -p lib/domain/usecases --proGenerates use cases with:
UseCasebase class extensionParamsclasses for clean parameters- Proper
Either<Failure, T>return types - Your project's import paths
// analytics_repository.dart
class AnalyticsRepository {
// Either pattern
Future<Either<Failure, AnalyticsData>> getAnalytics(DateTime date);
// Simple pattern
Future<int> getTotalUsers();
// Void with Either
Future<Either<Failure, void>> clearAnalyticsCache();
}Auto-detects and handles both patterns!
auto_use_case -r REPOSITORY_FILE -p OUTPUT_DIRECTORY [OPTIONS]| Option | Description | Example |
|---|---|---|
-r, --repository |
Path to your repository file | -r lib/repo.dart |
-p, --path |
Where to save generated use cases | -p lib/domain/usecases |
| Flag | Description | Example |
|---|---|---|
--pro |
Professional mode (with params classes) | --pro |
--simple |
Simple mode (direct parameters) | --simple |
-n, --name |
Custom repository class name | -n ApiClient |
--version |
Show CLI version | --version |
-h, --help |
Show help message | -h |
# Basic generation
auto_use_case -r lib/repo.dart -p lib/usecases
# Pro mode for Either/Failure
auto_use_case -r lib/repo.dart -p lib/usecases --pro
# Custom class name
auto_use_case -r lib/api.dart -p lib/usecases -n ApiClient
# Check CLI version
auto_use_case --versionHandles all Dart parameter types:
// Repository method
Future<Report> generateReport({
required DateTime startDate,
required DateTime endDate,
ReportType type = ReportType.detailed,
bool includeCharts = true,
List<String>? filters,
});
// Generated use case handles all parameters correctly# Feature-based structure
auto_use_case -r lib/features/auth/repositories/auth_repo.dart -p lib/features/auth/domain/usecases
# Layer-based structure
auto_use_case -r lib/data/repositories/user_repo.dart -p lib/domain/usecases
# Simple structure
auto_use_case -r lib/repository.dart -p lib/usecases
# Custom structure
auto_use_case -r packages/domain/lib/repositories/product_repo.dart -p packages/domain/lib/usecases# .github/workflows/generate_usecases.yml
name: Generate Use Cases
on: [push, pull_request]
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dart-lang/setup-dart@v1
- name: Install CLI tool
run: dart pub global activate auto_use_case
- name: Generate use cases
run: |
auto_use_case -r lib/repositories/user_repository.dart -p lib/domain/usecases --pro
auto_use_case -r lib/repositories/product_repository.dart -p lib/domain/usecases --pro
- name: Commit generated files
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
git add lib/domain/usecases/
git commit -m "chore: regenerate use cases" || echo "No changes to commit"
git pushIt's a CLI tool! You install it globally and run commands in your terminal, just like git, npm, or docker.
| Use Case | Recommended Method |
|---|---|
| Daily development | π’ Global CLI (dart pub global activate) |
| CI/CD pipelines | π‘ Project dependency (dart pub add --dev) |
| Team projects | π’ Global (each dev installs) |
| Version locking | π‘ Project (specify version in pubspec) |
Add Dart to your PATH:
# macOS/Linux
echo 'export PATH="$PATH:$HOME/.pub-cache/bin"' >> ~/.zshrc
source ~/.zshrc
# Windows: Add to PATH
# %USERPROFILE%\AppData\Local\Pub\Cache\binThe CLI reads your repository file and preserves all imports. If your repo imports dartz, equatable, failures.dart, and usecase.dart, the generated use cases will include them too.
Yes! The CLI only creates new files. It never modifies existing files. Delete old ones and regenerate if needed.
β
Future<T> - Simple return
β
Future<Either<Failure, T>> - Either pattern
β
Future<void> - Void return
β
Future<Either<Failure, void>> - Void with Either
β
Required: String id
β
Optional: String? optional
β
Named: {required String name}
β
Default values: int count = 1
β
Lists/Maps: List<User>, Map<String, dynamic>
β
import 'package:dartz/dartz.dart';
β
import 'package:equatable/equatable.dart';
β
Your custom: import 'package:myapp/core/errors/failures.dart';
β
Your base: import 'package:myapp/core/usecases/usecase.dart';
my_flutter_app/
βββ pubspec.yaml # Package: "myapp"
βββ lib/
β βββ core/
β β βββ errors/
β β β βββ failures.dart
β β βββ usecases/
β β βββ usecase.dart
β βββ features/
β βββ auth/
β βββ repositories/
β β βββ auth_repository.dart
β βββ domain/
β βββ usecases/ # β Generated here
// lib/features/auth/repositories/auth_repository.dart
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:myapp/core/errors/failures.dart';
class AuthRepository {
Future<Either<Failure, User>> login(String email, String password);
Future<Either<Failure, void>> logout();
Future<Either<Failure, User>> getCurrentUser();
}auto_use_case \
-r lib/features/auth/repositories/auth_repository.dart \
-p lib/features/auth/domain/usecases \
--pro// lib/features/auth/domain/usecases/login_use_case.dart
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:myapp/core/errors/failures.dart';
import 'package:myapp/core/usecases/usecase.dart';
import 'package:myapp/features/auth/domain/repositories/auth_repository.dart';
class LoginUseCase extends UseCase<User, LoginUseCaseParams> {
final AuthRepository repository;
LoginUseCase(this.repository);
@override
Future<Either<Failure, User>> call(LoginUseCaseParams params) {
return repository.login(params.email, params.password);
}
}
class LoginUseCaseParams extends Equatable {
final String email;
final String password;
const LoginUseCaseParams({
required this.email,
required this.password,
});
@override
List<Object?> get props => [email, password];
}Perfect import paths! Perfect project structure! Zero manual work!
Make sure your repository class is public:
// β
Public class
class UserRepository { ... }
// β Private class (won't work)
class _UserRepository { ... }Use absolute paths from project root:
# β Wrong
auto_use_case -r repository.dart -p usecases
# β
Right
auto_use_case -r lib/repository.dart -p lib/usecasesThe CLI auto-detects imports from your repository file. If wrong, you can:
- Manually fix imports once
- Ensure your repository has correct imports
- The generated files will mirror your repository's imports
# Global install
dart pub global activate auto_use_case
# Project dependency
dart pub upgrade auto_use_caseMIT License - see LICENSE file for details.
# π’ INSTALL AS CLI TOOL (Recommended)
dart pub global activate auto_use_case
# π GENERATE USE CASES
auto_use_case \
-r lib/features/auth/repositories/auth_repository.dart \
-p lib/features/auth/domain/usecases \
--pro
# Watch use cases appear instantly! β¨A CLI tool for Flutter developers who value their time
- Issues: GitHub Issues
- Questions: Check FAQ section above
- Feature Requests: Open a GitHub discussion
β Star the repo if this saves you time!
## Key Improvements: π₯
1. **Clearly states it's a CLI tool** - Multiple mentions
2. **Shows terminal usage** - Emphasizes command-line nature
3. **Generic examples** - Uses `myapp` instead of specific names
4. **Import preservation** - Shows how `dartz`, `equatable`, `failures.dart`, `usecase.dart` are preserved
5. **Real-world structure** - Shows complete project example
6. **Comparison table** - Global CLI vs project dependency
This makes it **crystal clear** that it's a CLI tool, not a library! π