Añadir 03-env.md
347
03-env.md.-.md
Normal file
347
03-env.md.-.md
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
# Variables de Entorno
|
||||||
|
|
||||||
|
Configuración de `.env` para desarrollo local y producción.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backend — `.env`
|
||||||
|
|
||||||
|
Crea `basura_backend/.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ========================================
|
||||||
|
# CONFIGURACIÓN DEL SIMULADOR
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# Intervalo de actualización del camión (segundos)
|
||||||
|
SIM_TICK_SECONDS=10
|
||||||
|
|
||||||
|
# Umbral de ETA para notificar proximidad (minutos)
|
||||||
|
SIM_ETA_ALERT_MINUTES=10
|
||||||
|
|
||||||
|
# Multiplicador de velocidad del simulador
|
||||||
|
# 1.0 = tiempo real
|
||||||
|
# 2.0 = doble velocidad (útil para demos rápidas)
|
||||||
|
# 0.5 = mitad de velocidad (útil para debug)
|
||||||
|
SIM_SPEED_MULTIPLIER=1.0
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# BASE DE DATOS
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# Ruta del archivo SQLite
|
||||||
|
DATABASE_PATH=./basura.db
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# SERVIDOR
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# Host (0.0.0.0 para aceptar conexiones externas)
|
||||||
|
HOST=0.0.0.0
|
||||||
|
|
||||||
|
# Puerto del servidor
|
||||||
|
PORT=8000
|
||||||
|
|
||||||
|
# Hot reload en desarrollo (True/False)
|
||||||
|
RELOAD=True
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# CORS (desarrollo)
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# Permitir todos los orígenes en desarrollo
|
||||||
|
# En producción, especificar dominios exactos
|
||||||
|
CORS_ORIGINS=*
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# JWT (para cuando Persona A integre auth)
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# Secret key para firmar tokens JWT
|
||||||
|
# CAMBIAR EN PRODUCCIÓN a una clave aleatoria fuerte
|
||||||
|
JWT_SECRET=super-secret-key-change-in-production
|
||||||
|
|
||||||
|
# Expiración del token (minutos)
|
||||||
|
JWT_EXPIRATION_MINUTES=1440 # 24 horas
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# LOGGING
|
||||||
|
# ========================================
|
||||||
|
|
||||||
|
# Nivel de log: DEBUG, INFO, WARNING, ERROR
|
||||||
|
LOG_LEVEL=INFO
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usar las variables en el código
|
||||||
|
|
||||||
|
```python
|
||||||
|
# app/core/config.py
|
||||||
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
|
class Settings(BaseSettings):
|
||||||
|
sim_tick_seconds: int = 10
|
||||||
|
sim_eta_alert_minutes: int = 10
|
||||||
|
sim_speed_multiplier: float = 1.0
|
||||||
|
database_path: str = "./basura.db"
|
||||||
|
host: str = "0.0.0.0"
|
||||||
|
port: int = 8000
|
||||||
|
reload: bool = True
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
env_file = ".env"
|
||||||
|
|
||||||
|
settings = Settings()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Frontend — `.env` (Flutter)
|
||||||
|
|
||||||
|
Flutter **no soporta `.env` nativamente**, pero hay opciones:
|
||||||
|
|
||||||
|
### Opción A: Usar `flutter_dotenv`
|
||||||
|
|
||||||
|
**1. Instalar:**
|
||||||
|
```yaml
|
||||||
|
# pubspec.yaml
|
||||||
|
dependencies:
|
||||||
|
flutter_dotenv: ^5.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Crear `.env`:**
|
||||||
|
```bash
|
||||||
|
# basura_app/.env
|
||||||
|
API_BASE_URL=http://10.0.2.2:8000
|
||||||
|
WS_BASE_URL=ws://10.0.2.2:8000
|
||||||
|
ENVIRONMENT=development
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Declarar en pubspec:**
|
||||||
|
```yaml
|
||||||
|
flutter:
|
||||||
|
assets:
|
||||||
|
- .env
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Cargar en main.dart:**
|
||||||
|
```dart
|
||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
|
|
||||||
|
Future<void> main() async {
|
||||||
|
await dotenv.load(fileName: ".env");
|
||||||
|
runApp(ProviderScope(child: MyApp()));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**5. Usar en el código:**
|
||||||
|
```dart
|
||||||
|
final baseUrl = dotenv.env['API_BASE_URL'] ?? 'http://localhost:8000';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Opción B: Flavors (recomendado para producción)
|
||||||
|
|
||||||
|
Permite tener **configuraciones separadas** para dev, staging, prod.
|
||||||
|
|
||||||
|
**1. Crear archivos de configuración:**
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// lib/core/config/environment.dart
|
||||||
|
enum Environment { dev, staging, prod }
|
||||||
|
|
||||||
|
class EnvironmentConfig {
|
||||||
|
final String apiBaseUrl;
|
||||||
|
final String wsBaseUrl;
|
||||||
|
final Environment env;
|
||||||
|
|
||||||
|
const EnvironmentConfig({
|
||||||
|
required this.apiBaseUrl,
|
||||||
|
required this.wsBaseUrl,
|
||||||
|
required this.env,
|
||||||
|
});
|
||||||
|
|
||||||
|
static const dev = EnvironmentConfig(
|
||||||
|
apiBaseUrl: 'http://10.0.2.2:8000',
|
||||||
|
wsBaseUrl: 'ws://10.0.2.2:8000',
|
||||||
|
env: Environment.dev,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const prod = EnvironmentConfig(
|
||||||
|
apiBaseUrl: 'https://api.basura.onlinces.net',
|
||||||
|
wsBaseUrl: 'wss://api.basura.onlinces.net',
|
||||||
|
env: Environment.prod,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Crear entry points:**
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// lib/main_dev.dart
|
||||||
|
void main() {
|
||||||
|
runApp(ProviderScope(
|
||||||
|
overrides: [
|
||||||
|
envConfigProvider.overrideWithValue(EnvironmentConfig.dev),
|
||||||
|
],
|
||||||
|
child: MyApp(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// lib/main_prod.dart
|
||||||
|
void main() {
|
||||||
|
runApp(ProviderScope(
|
||||||
|
overrides: [
|
||||||
|
envConfigProvider.overrideWithValue(EnvironmentConfig.prod),
|
||||||
|
],
|
||||||
|
child: MyApp(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Correr según entorno:**
|
||||||
|
```bash
|
||||||
|
# Desarrollo
|
||||||
|
fvm flutter run -t lib/main_dev.dart
|
||||||
|
|
||||||
|
# Producción
|
||||||
|
fvm flutter run -t lib/main_prod.dart --release
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuraciones específicas por entorno
|
||||||
|
|
||||||
|
### Desarrollo Local
|
||||||
|
|
||||||
|
**Backend:**
|
||||||
|
```bash
|
||||||
|
SIM_TICK_SECONDS=5 # Más rápido para debug
|
||||||
|
SIM_SPEED_MULTIPLIER=2.0 # Doble velocidad
|
||||||
|
LOG_LEVEL=DEBUG # Logs detallados
|
||||||
|
```
|
||||||
|
|
||||||
|
**Flutter:**
|
||||||
|
```
|
||||||
|
API_BASE_URL=http://10.0.2.2:8000 # Emulador Android
|
||||||
|
WS_BASE_URL=ws://10.0.2.2:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Demo en Hackathon
|
||||||
|
|
||||||
|
**Backend:**
|
||||||
|
```bash
|
||||||
|
SIM_TICK_SECONDS=10 # Velocidad normal
|
||||||
|
SIM_ETA_ALERT_MINUTES=5 # Notificar más rápido
|
||||||
|
SIM_SPEED_MULTIPLIER=1.5 # Un poco más rápido para demo
|
||||||
|
```
|
||||||
|
|
||||||
|
**Flutter:**
|
||||||
|
```
|
||||||
|
API_BASE_URL=http://192.168.x.x:8000 # IP de la PC del presentador
|
||||||
|
WS_BASE_URL=ws://192.168.x.x:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Producción (si despliegan después del hackathon)
|
||||||
|
|
||||||
|
**Backend:**
|
||||||
|
```bash
|
||||||
|
SIM_TICK_SECONDS=10
|
||||||
|
SIM_ETA_ALERT_MINUTES=10
|
||||||
|
SIM_SPEED_MULTIPLIER=1.0
|
||||||
|
DATABASE_PATH=/var/basura/basura.db
|
||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=8000
|
||||||
|
RELOAD=False
|
||||||
|
CORS_ORIGINS=https://basura.onlinces.net
|
||||||
|
JWT_SECRET=<generado con secrets.token_urlsafe(32)>
|
||||||
|
LOG_LEVEL=WARNING
|
||||||
|
```
|
||||||
|
|
||||||
|
**Flutter:**
|
||||||
|
```
|
||||||
|
API_BASE_URL=https://api.basura.onlinces.net
|
||||||
|
WS_BASE_URL=wss://api.basura.onlinces.net
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Secretos sensibles — **NO commitear**
|
||||||
|
|
||||||
|
### `.gitignore` debe incluir:
|
||||||
|
|
||||||
|
```gitignore
|
||||||
|
# Backend
|
||||||
|
basura_backend/.env
|
||||||
|
basura_backend/*.db
|
||||||
|
basura_backend/venv/
|
||||||
|
|
||||||
|
# Flutter
|
||||||
|
basura_app/.env
|
||||||
|
basura_app/.env.*
|
||||||
|
basura_app/build/
|
||||||
|
basura_app/.fvm/
|
||||||
|
|
||||||
|
# Secretos
|
||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
*.p12
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Provider compartido para configuración (Flutter)
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// lib/core/config/env_provider.dart
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'environment.dart';
|
||||||
|
|
||||||
|
final envConfigProvider = Provider<EnvironmentConfig>((ref) {
|
||||||
|
throw UnimplementedError('EnvConfig debe ser overridden en main.dart');
|
||||||
|
});
|
||||||
|
|
||||||
|
final apiBaseUrlProvider = Provider<String>((ref) {
|
||||||
|
return ref.watch(envConfigProvider).apiBaseUrl;
|
||||||
|
});
|
||||||
|
|
||||||
|
final wsBaseUrlProvider = Provider<String>((ref) {
|
||||||
|
return ref.watch(envConfigProvider).wsBaseUrl;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing con diferentes configuraciones
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Dev rápido
|
||||||
|
SIM_TICK_SECONDS=1 SIM_SPEED_MULTIPLIER=10.0 uvicorn app.main:app
|
||||||
|
|
||||||
|
# Demo lento (explicar paso a paso)
|
||||||
|
SIM_TICK_SECONDS=30 uvicorn app.main:app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flutter
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Probar contra backend local
|
||||||
|
fvm flutter run --dart-define=API_URL=http://10.0.2.2:8000
|
||||||
|
|
||||||
|
# Probar contra staging
|
||||||
|
fvm flutter run --dart-define=API_URL=https://staging.basura.net
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Siguiente paso
|
||||||
|
|
||||||
|
- [Endpoints REST](../api/01-endpoints.md) — usar las URLs configuradas
|
||||||
|
- [WebSocket](../api/02-websocket.md) — conectar con la URL WS
|
||||||
|
- [Troubleshooting](../troubleshooting/01-errores-comunes.md) — solucionar problemas de conexión
|
||||||
Reference in New Issue
Block a user