Files
retail/docs/API_ARCHITECTURE.md
Phuoc Nguyen b94c158004 runable
2025-10-10 16:38:07 +07:00

418 lines
27 KiB
Markdown

# API Integration Architecture
## Complete Data Flow Diagram
```
┌─────────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ ProductsPage │ │ CategoriesPage│ │ HomePage │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └──────────────────┴──────────────────┘ │
│ │ │
└────────────────────────────┼────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ RIVERPOD PROVIDERS │
│ │
│ ┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ProductsProvider │ │CategoriesProvider│ │ NetworkProvider │ │
│ └────────┬────────┘ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │ │
└───────────┼─────────────────────┼─────────────────────┼────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ USE CASES (Domain) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │GetAllProducts│ │GetCategories │ │SearchProducts│ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
└─────────┼──────────────────┼──────────────────┼────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ REPOSITORIES (Data) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ProductRepositoryImpl │ │
│ │ │ │
│ │ - Offline-first logic │ │
│ │ - Exception → Failure conversion │ │
│ │ - Cache + Remote coordination │ │
│ └──────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Local Source │ │ Remote Source│ │
│ │ (Hive) │ │ (API) │ │
│ └──────────────┘ └──────┬───────┘ │
└─────────────────────────────────────────┼──────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ NETWORK LAYER (Core) │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ DIO CLIENT │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────────┐ │ │
│ │ │ INTERCEPTORS │ │ │
│ │ │ │ │ │
│ │ │ 1. Logging Interceptor │ │ │
│ │ │ → Log requests/responses │ │ │
│ │ │ │ │ │
│ │ │ 2. Auth Interceptor │ │ │
│ │ │ → Add auth headers │ │ │
│ │ │ → Handle 401 errors │ │ │
│ │ │ │ │ │
│ │ │ 3. Error Interceptor │ │ │
│ │ │ → Map status codes to exceptions │ │ │
│ │ │ → Extract error messages │ │ │
│ │ │ │ │ │
│ │ │ 4. Retry Interceptor │ │ │
│ │ │ → Retry on timeout/connection errors │ │ │
│ │ │ → Exponential backoff │ │ │
│ │ └────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ HTTP Methods: GET, POST, PUT, DELETE, PATCH │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ NETWORK INFO │ │
│ │ │ │
│ │ - Check connectivity status │ │
│ │ - Monitor connectivity changes │ │
│ │ - Detect connection type (WiFi/Mobile) │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ BACKEND API │
│ │
│ GET /api/v1/products │
│ GET /api/v1/products/:id │
│ GET /api/v1/products/category/:categoryId │
│ GET /api/v1/products/search?q=query │
│ POST /api/v1/products/sync │
│ │
│ GET /api/v1/categories │
│ GET /api/v1/categories/:id │
│ POST /api/v1/categories/sync │
└─────────────────────────────────────────────────────────────────────┘
```
---
## Error Handling Flow
```
┌──────────────┐
│ API Request │
└──────┬───────┘
┌──────────────────┐
│ Network Check │
│ (NetworkInfo) │
└──────┬───────────┘
├─── No Connection ────────────────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌────────────────────┐
│ Send Request │ │ NoInternetException│
│ via DioClient │ └────────────────────┘
└──────┬───────────┘ │
│ │
├─── Timeout ──────────────────────────────┤
│ │
├─── Connection Error ─────────────────────┤
│ │
▼ ▼
┌──────────────────┐ ┌────────────────────┐
│ Retry Interceptor│───── Max retries ──│ TimeoutException │
│ (3 attempts) │ reached │ ConnectionException│
└──────┬───────────┘ └────────────────────┘
│ │
│ Success after retry │
▼ ▼
┌──────────────────┐ ┌────────────────────┐
│ Error Interceptor│ │ Repository │
│ (Status codes) │ │ Converts to │
└──────┬───────────┘ │ Failure │
│ └────────────────────┘
│ │
├─── 400 ──────── BadRequestException │
├─── 401 ──────── UnauthorizedException │
├─── 403 ──────── ForbiddenException │
├─── 404 ──────── NotFoundException │
├─── 422 ──────── ValidationException │
├─── 429 ──────── RateLimitException │
├─── 500+ ─────── ServerException │
│ │
▼ ▼
┌──────────────────┐ ┌────────────────────┐
│ Success Response │ │ UI Layer │
│ Parse JSON │ │ Shows Error │
│ Return Model │ │ Message │
└──────────────────┘ └────────────────────┘
```
---
## Authentication Flow
```
┌─────────────────┐
│ User Login │
└────────┬────────┘
┌─────────────────┐
│ Auth API Call │
│ POST /login │
└────────┬────────┘
┌─────────────────────────┐
│ Receive JWT Token │
│ { token: "...", │
│ refreshToken: "..." }│
└────────┬────────────────┘
┌─────────────────────────┐
│ AuthInterceptor │
│ .setAuthToken(token) │
└────────┬────────────────┘
┌─────────────────────────┐
│ All subsequent requests │
│ include: │
│ Authorization: │
│ Bearer <token> │
└────────┬────────────────┘
├──── Token Valid ────────► Continue Request
├──── 401 Unauthorized ───┐
│ │
▼ ▼
┌─────────────────────────┐ ┌────────────────────┐
│ AuthInterceptor detects │ │ Refresh Token │
│ 401 response │ │ POST /refresh │
└────────┬────────────────┘ └────────┬───────────┘
│ │
│ ▼
│ ┌────────────────────┐
│ │ Get New Token │
│ └────────┬───────────┘
│ │
│ ▼
│ ┌────────────────────┐
│ │ Update Token │
│ │ Retry Request │
│ └────────────────────┘
┌─────────────────────────┐
│ Refresh Failed? │
│ Clear token │
│ Navigate to Login │
└─────────────────────────┘
```
---
## Data Synchronization Flow
```
┌────────────────┐
│ App Launch │
└───────┬────────┘
┌────────────────────────┐
│ Load from Hive Cache │
│ (Instant UI) │
└───────┬────────────────┘
┌────────────────────────┐
│ Check Network Status │
└───────┬────────────────┘
├─── Offline ──────────────────────┐
│ │
▼ ▼
┌────────────────────────┐ ┌──────────────────┐
│ Fetch from API │ │ Use Cached Data │
│ (Background) │ │ Show Offline UI │
└───────┬────────────────┘ └──────────────────┘
┌────────────────────────┐
│ Compare with Cache │
│ (by timestamp) │
└───────┬────────────────┘
├─── New Data Available ──┐
│ │
▼ ▼
┌────────────────────────┐ ┌──────────────────────┐
│ Update Hive Cache │ │ No Changes │
└───────┬────────────────┘ │ Keep Current Data │
│ └──────────────────────┘
┌────────────────────────┐
│ Notify UI │
│ (Riverpod ref.refresh) │
└───────┬────────────────┘
┌────────────────────────┐
│ UI Updates │
│ Show Fresh Data │
└────────────────────────┘
```
---
## Component Dependencies
```
┌──────────────────────────────────────────────┐
│ GetIt Service Locator │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ Connectivity (External) │ │
│ └────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────┐ │
│ │ NetworkInfo │ │
│ │ - NetworkInfoImpl(Connectivity) │ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ DioClient │ │
│ │ - Dio instance │ │
│ │ - Interceptors │ │
│ └────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────┐ │
│ │ ProductRemoteDataSource │ │
│ │ - ProductRemoteDataSourceImpl(Dio) │ │
│ │ OR │ │
│ │ - ProductRemoteDataSourceMock() │ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ CategoryRemoteDataSource │ │
│ │ - CategoryRemoteDataSourceImpl(Dio) │ │
│ │ OR │ │
│ │ - CategoryRemoteDataSourceMock() │ │
│ └────────────────────────────────────────┘ │
│ │
│ (Future: Repositories, UseCases) │
└──────────────────────────────────────────────┘
```
---
## File Dependencies Graph
```
main.dart
├─► injection_container.dart
│ │
│ ├─► dio_client.dart
│ │ │
│ │ └─► api_interceptor.dart
│ │ │
│ │ └─► api_constants.dart
│ │ └─► exceptions.dart
│ │
│ ├─► network_info.dart
│ │ │
│ │ └─► connectivity_plus
│ │
│ ├─► product_remote_datasource.dart
│ │ │
│ │ ├─► dio_client.dart
│ │ ├─► product_model.dart
│ │ ├─► api_constants.dart
│ │ └─► exceptions.dart
│ │
│ └─► category_remote_datasource.dart
│ │
│ ├─► dio_client.dart
│ ├─► category_model.dart
│ ├─► api_constants.dart
│ └─► exceptions.dart
└─► app.dart (Riverpod providers)
```
---
## Testing Strategy
```
┌─────────────────────────────────────────────────────────┐
│ TESTING PYRAMID │
│ │
│ ┌───────┐ │
│ │ E2E │ │
│ │ Tests │ │
│ └───┬───┘ │
│ │ │
│ ┌───────┴───────┐ │
│ │ Integration │ │
│ │ Tests │ │
│ └───────┬───────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ │ Widget Tests │ │
│ │ (with mock providers)│ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ │ Unit Tests │ │
│ │ - Data Sources (Mock/Real) │ │
│ │ - Network Info │ │
│ │ - DioClient │ │
│ │ - Interceptors │ │
│ │ - Exception Handling │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Test Coverage Goals:
- Unit Tests: 80%+
- Widget Tests: 60%+
- Integration Tests: Key flows
- E2E Tests: Critical paths
```
---
**Architecture Status**: ✅ Complete
This architecture provides:
- Clean separation of concerns
- Offline-first capability
- Robust error handling
- Easy testing and mocking
- Scalable and maintainable structure