---
description: "Clean Architecture conventions for TestApp"
alwaysApply: true
---

# Clean Architecture — TestApp

## Layer structure
```
lib/features/[feature]/
  ├── domain/
  │   ├── entities/        ← Pure Dart, no framework imports
  │   ├── repositories/    ← Abstract interfaces only
  │   └── usecases/        ← Single-responsibility business operations
  ├── data/
  │   ├── datasources/     ← Remote (API) + Local (cache) implementations
  │   ├── models/          ← DTOs with fromJson/toJson (can use Freezed)
  │   └── repositories/    ← Implements domain/repositories interfaces
  └── presentation/
      ├── bloc/ or notifiers/
      ├── pages/
      └── widgets/
```

## Import rules (STRICTLY ENFORCED by arch-guard hook)
- presentation/ MUST NOT import from data/
- domain/ MUST NOT import from data/ or presentation/
- data/ CAN import from domain/ (implements interfaces)
- Use dependency injection to invert data → domain dependency

## UseCase pattern
```dart
// One UseCase = one operation = one method
class GetProductsUseCase {
  final ProductRepository _repository;
  const GetProductsUseCase(this._repository);

  Future<Either<AppError, List<Product>>> call(ProductFilter filter) =>
      _repository.getProducts(filter);
}
```

## Entity rules
- Entities are pure Dart — zero Flutter or framework imports
- Entities are immutable — use `final` fields + factory constructors
- Entities NEVER have `fromJson`/`toJson` — that belongs in the data layer model

## Repository rules
- Domain defines the **interface** (abstract class)
- Data layer **implements** it
- Use `Either<Failure, T>` or `Result<T>` return types — never throw in domain

## Dependency injection
- Use `injectable` + `get_it` if `codegen` includes `injectable`
- All UseCases injected into BLoC/Notifier via constructor
- `DataSource → Repository → UseCase → Bloc` dependency direction
