React Native Template con Arquitectura Hexagonal Completa
Este es un template de React Native con Arquitectura Hexagonal (Ports & Adapters) completamente implementada, siguiendo los principios SOLID y Clean Architecture. Bootstrapped usando @react-native-community/cli.
🎯 Template listo para producción con 30+ tests, Value Objects, Result Pattern, Dependency Injection y Logger estructurado.
Este no es solo otro template de React Native. Implementa una verdadera Arquitectura Hexagonal con:
- ✅ Ports & Adapters - Desacoplamiento real entre capas
- ✅ Value Objects -
ProductNumber,Money,ExpirationDatecon validación - ✅ Result Pattern - Manejo funcional de errores sin try-catch
- ✅ Dependency Injection - UseCases completamente desacoplados
- ✅ Domain Exceptions - 7 excepciones específicas de negocio
- ✅ 30+ Tests Unitarios - Cobertura de Value Objects y Repositories
- ✅ Logger Estructurado - 4 niveles con contexto enriquecido
- ✅ Repositorios Intercambiables - Mock
↔️ HTTP sin cambiar código
- Características
- Requisitos Previos
- Instalación
- Comenzando
- Stack Tecnológico
- Arquitectura
- Estructura del Proyecto
- Scripts Disponibles
- Testing
- Configuración
- Principios SOLID
- Métricas del Proyecto
- Próximos Pasos
- Troubleshooting
- Recursos de Aprendizaje
- ⚡ React Native 0.82.0 con New Architecture habilitada
- 🏗️ Arquitectura Hexagonal (Ports & Adapters) implementada completamente
- 📦 TypeScript 5.9.3 para type safety
- 🎨 React 19.1.1 con las últimas características
- 🧭 React Navigation 7.x para navegación
- 💾 AsyncStorage 2.x para persistencia de datos
- 🔥 Axios 1.12.2 para peticiones HTTP
- ✅ Zod 4.x para validación de esquemas estricta
- 🎯 Ports & Adapters - Interfaces explícitas (ICreditCardRepository, ILogger)
- 🔄 Inversión de Dependencias (DIP) - UseCases desacoplados con inyección de dependencias
- 💎 Value Objects - ProductNumber, Money, ExpirationDate con validación
- 🎭 Result Pattern - Manejo funcional de errores sin try-catch excesivos
- 🚨 Domain Exceptions - 7 excepciones específicas de negocio
- 📝 Logger Service - Logging estructurado con niveles (DEBUG, INFO, WARN, ERROR)
- 🏪 Repositorios Intercambiables - MockRepository y HttpRepository
- 🎯 Path aliases configurados (@app, @core, @components, @helpers)
- 📱 Safe Area Context para manejo de áreas seguras
- 🧪 30+ Tests Unitarios con Jest (Value Objects, Repositories, UseCases)
- 📏 ESLint & Prettier para consistencia de código
- 🌍 Variables de Entorno (.env.development, .env.staging, .env.production)
- 📚 Documentación Completa - JSDoc en todo el código
Asegúrate de haber completado las instrucciones de React Native - Environment Setup antes de proceder.
Requisitos mínimos:
- Node.js: >= 20
- React Native: 0.82.0
- iOS: Xcode 15+ (para desarrollo iOS)
- Android: Android Studio con SDK 35, NDK 26.1.10909125
Clona el repositorio e instala las dependencias:
# Clonar el repositorio
git clone https://github.com/raicoacosta/RNTemplateHexagonal.git
cd RNTemplateHexagonal
# Instalar dependencias
yarn install
# Para iOS, instalar pods
cd ios && pod install && cd ..Primero, necesitas iniciar Metro, el bundler de JavaScript que viene con React Native:
yarn startDeja que Metro Bundler corra en su propia terminal. Abre una nueva terminal desde la raíz de tu proyecto React Native y ejecuta:
yarn androidyarn iosSi todo está configurado correctamente, deberías ver tu nueva app ejecutándose en tu Emulador de Android o Simulador de iOS mostrando 3 tarjetas de crédito mock (Platinum, Oro, Black).
También puedes ejecutar la app directamente desde Android Studio o Xcode.
Ejecuta los tests para verificar que todo funciona:
yarn testDeberías ver 30 tests pasando ✅
El template incluye un ejemplo completo del módulo CreditCards:
- Value Objects:
ProductNumber,Money,ExpirationDate - UseCases: 4 casos de uso específicos con Result Pattern
- Repositorios: Mock y HTTP implementados
- Tests: Cobertura completa de Value Objects y Repositories
Ahora que has ejecutado exitosamente la app, modifícala:
- Abre
src/app/App.tsxen tu editor de texto y edita algunas líneas. - Para Android: Presiona la tecla R dos veces o selecciona "Reload" desde el Developer Menu (Ctrl + M en Windows/Linux o Cmd ⌘ + M en macOS).
- Para iOS: Presiona Cmd ⌘ + R en tu Simulador iOS para recargar la app.
import {useCreditCardUseCases} from '@core/Modules/CreditCards/Applications/UseCases';
function MyComponent() {
const {getAllCreditCards, createCreditCard} = useCreditCardUseCases();
const [cards, setCards] = useState<CreditCard[]>([]);
const [error, setError] = useState<string>();
useEffect(() => {
loadCards();
}, []);
const loadCards = async () => {
const result = await getAllCreditCards.execute();
if (result.isSuccess) {
setCards(result.getValue());
} else {
setError(result.getError().message);
}
};
return (
<View>
{cards.map(card => (
<Text key={card.productNumber}>{card.alias}</Text>
))}
</View>
);
}import {ProductNumber} from '@core/Modules/CreditCards/Domain/ValueObjects/ProductNumber';
import {Money, Currency} from '@core/Modules/CreditCards/Domain/ValueObjects/Money';
// ProductNumber con validación
const productNumber = ProductNumber.create('4076733111412174');
console.log(productNumber.getMasked()); // "****-****-****-2174"
// Money con operaciones seguras
const balance = Money.create(1000, Currency.USD);
const payment = Money.create(200, Currency.USD);
const newBalance = balance.subtract(payment); // Money(800, USD)
console.log(newBalance.format()); // "USD 800.00"// src/app/core/Modules/CreditCards/Applications/UseCases/index.tsx
// 1. Desarrollo con Mock (actual)
const repository: ICreditCardRepository = new MockCreditCardRepository();
// 2. Producción con HTTP (cambiar cuando API esté lista)
const repository: ICreditCardRepository = new HttpCreditCardRepository(httpImpl);
// El resto del código no cambia - Principio de Inversión de Dependencias ✅
const useCases = {
getAllCreditCards: new GetAllCreditCardsUseCase(repository, logger),
// ... más casos de uso
};| Librería | Versión | Descripción |
|---|---|---|
| React Native | 0.82.0 | Framework principal |
| React | 19.1.1 | Librería UI con Actions y use hook |
| TypeScript | 5.9.3 | Superset tipado de JavaScript |
| Librería | Versión | Descripción |
|---|---|---|
| @react-navigation/native | 7.1.18 | Navegación base |
| @react-navigation/native-stack | 7.3.28 | Stack navigator nativo |
| @react-navigation/stack | 7.4.10 | Stack navigator JS |
| react-native-screens | 4.17.1 | Optimización de pantallas |
| react-native-gesture-handler | 2.28.0 | Gestos nativos |
| react-native-safe-area-context | 5.6.1 | Safe areas nativas |
| Librería | Versión | Descripción |
|---|---|---|
| axios | 1.12.2 | Cliente HTTP |
| zod | 4.1.12 | Validación de esquemas TypeScript-first |
| @react-native-async-storage/async-storage | 2.2.0 | Almacenamiento persistente |
| Librería | Versión | Descripción |
|---|---|---|
| @react-native/eslint-config | 0.82.0 | Configuración ESLint |
| prettier | 3.6.2 | Formateador de código |
| jest | 29.7.0 | Framework de testing |
| babel-plugin-module-resolver | 5.0.2 | Resolución de paths |
Este proyecto implementa una Arquitectura Hexagonal (también conocida como Ports & Adapters), que es parte de la familia de Clean Architectures propuesta por Robert C. Martin (Uncle Bob).
-
Mantenibilidad: Una arquitectura bien estructurada facilita la mantenibilidad del software a lo largo del tiempo. Permite a los desarrolladores realizar cambios y mejoras en el sistema de manera más sencilla y con menos riesgo de introducir errores.
-
Separación de preocupaciones: Una buena arquitectura divide el sistema en capas y componentes con responsabilidades específicas. Esto facilita la comprensión del código y permite a los desarrolladores enfocarse en aspectos particulares del sistema sin tener que preocuparse por todo al mismo tiempo.
-
Flexibilidad: Al desacoplar las diferentes partes del sistema, una arquitectura sólida permite reemplazar o actualizar componentes de manera más fácil. Por ejemplo, si un componente de la infraestructura necesita ser reemplazado por una tecnología diferente, el impacto en el resto del sistema será mínimo.
-
Escalabilidad: Una arquitectura bien definida facilita la escalabilidad del sistema, permitiendo agregar nuevas funcionalidades o mejorar el rendimiento sin tener que rediseñar la aplicación completa.
-
Mantener el costo de desarrollo constante: Una arquitectura efectiva permite que el costo de desarrollo se mantenga constante a lo largo del tiempo, evitando que aumente exponencialmente a medida que el proyecto crece y evoluciona.
-
Facilitar la incorporación de nuevos miembros al equipo: Una buena arquitectura hace que sea más fácil para los nuevos miembros del equipo comprender y contribuir al proyecto, ya que proporciona una estructura clara y bien organizada.
-
Desacoplar componentes: Desacoplar componentes es clave para lograr una arquitectura flexible y mantenible. Esto permite reemplazar o modificar partes del sistema sin afectar al resto, lo que facilita la adaptación a cambios en los requisitos o las tecnologías.
-
Separación de preocupaciones: La arquitectura debe dividir el sistema en capas y componentes con responsabilidades específicas. Esto facilita la comprensión del código y permite a los desarrolladores enfocarse en aspectos particulares del sistema sin tener que preocuparse por todo al mismo tiempo.
-
Permitir la evolución del sistema: Una buena arquitectura de software permite que el sistema evolucione y se adapte a nuevos requisitos, cambios en la tecnología o en el entorno.
La Clean Architecture se basa en varios principios de diseño, como la inversión de dependencias, el principio de responsabilidad única y el principio de segregación de interfaces. Estos principios ayudan a guiar la organización del código y las relaciones entre los diferentes componentes del sistema.
- Principio de responsabilidad única (SRP): Cada módulo, clase o función debe tener una única responsabilidad.
- Principio Abierto/Cerrado (OCP): Los módulos, clases o funciones deben ser abiertos para la extensión, pero cerrados para la modificación.
- Principio de sustitución de Liskov (LSP): Los objetos de una clase derivada deben poder sustituir a los objetos de la clase base sin afectar la corrección del programa.
- Principio de segregación de interfaces (ISP): Los clientes no deben verse obligados a depender de interfaces que no utilizan.
- Principio de inversión de dependencias (DIP): Los módulos de alto nivel no deben depender de los módulos de bajo nivel. Ambos deben depender de abstracciones.
La Clean Architecture se compone de varias capas concéntricas, cada una con responsabilidades específicas:
-
Capa de dominio (Domain): Esta capa contiene la lógica de negocio principal y las reglas del dominio. Incluye entidades, objetos de valor y lógica de dominio. Las entidades son objetos que tienen una identidad única y representan conceptos clave del dominio del problema. Los objetos de valor son inmutables y se definen por sus atributos en lugar de una identidad única.
-
Capa de aplicación (Application): Esta capa se encarga de coordinar y orquestar la lógica de negocio en casos de uso específicos. Los casos de uso representan acciones o flujos de trabajo que los usuarios pueden realizar en la aplicación. La capa de aplicación interactúa con la capa de dominio y la capa de infraestructura, pero no contiene lógica de negocio específica.
-
Capa de infraestructura (Infrastructure): Esta capa proporciona implementaciones concretas de interfaces definidas en las capas de dominio y aplicación. Incluye la comunicación con sistemas externos, como APIs, Storage, Cámara, etc. La capa de infraestructura es responsable de la persistencia de datos, la gestión de conexiones y la implementación de detalles técnicos.
-
Capa de presentación (Presentation): Esta capa es responsable de la interacción con el usuario y la representación visual de la aplicación. Incluye componentes de interfaz de usuario, como pantallas y componentes, así como la lógica de presentación, como la validación de formularios y la manipulación del estado de la interfaz de usuario.
Este proyecto combina la Arquitectura Hexagonal con Vertical Slicing, un enfoque para organizar y estructurar el código de una aplicación en función de características o módulos, en lugar de agruparlos por capas técnicas.
Beneficios del Vertical Slicing:
- ✅ Facilita la colaboración entre equipos
- ✅ Hace que el código sea más fácil de mantener y navegar
- ✅ Permite trabajar en características individuales sin interferencias
- ✅ Mantiene una estructura de proyecto clara y coherente
Al aplicar el Vertical Slicing, cada característica o módulo tiene todos los archivos relacionados agrupados en una carpeta. Esto incluye componentes, servicios, modelos y archivos de infraestructura relacionados con esa característica específica.
RNTemplateHexagonal/
├── android/ # Código nativo Android
│ ├── app/
│ │ ├── build.gradle # Configuración Gradle de la app
│ │ └── src/
│ │ └── main/
│ │ ├── java/com/rntemplatehexagonal/
│ │ │ ├── MainActivity.kt
│ │ │ └── MainApplication.kt
│ │ ├── res/ # Recursos Android
│ │ └── AndroidManifest.xml
│ ├── build.gradle # Configuración Gradle raíz
│ └── gradle.properties # Propiedades Gradle (New Architecture habilitada)
│
├── ios/ # Código nativo iOS
│ ├── RNTemplateHexagonal/
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.mm
│ │ └── Info.plist
│ ├── RNTemplateHexagonal.xcodeproj/
│ ├── RNTemplateHexagonal.xcworkspace/
│ └── Podfile # Dependencias CocoaPods
│
├── src/
│ └── app/
│ ├── App.tsx # Componente principal (con Result Pattern)
│ │
│ ├── core/ # Core de la aplicación
│ │ │
│ │ ├── Infrastructure/ # Implementaciones de infraestructura
│ │ │ ├── Contracts/ # Interfaces y contratos (Ports)
│ │ │ │ ├── Http.interface.ts
│ │ │ │ ├── Logger.interface.ts # ← NUEVO
│ │ │ │ ├── Methods.ts
│ │ │ │ └── Storage.interface.ts
│ │ │ │
│ │ │ ├── Http/ # Implementación HTTP (Axios)
│ │ │ │ ├── Http.implementation.ts
│ │ │ │ └── index.tsx
│ │ │ │
│ │ │ ├── Logger/ # ← NUEVO - Logger Service
│ │ │ │ └── LoggerService.ts
│ │ │ │
│ │ │ └── Storage/ # Implementación Storage
│ │ │ └── async/
│ │ │ ├── AsyncStorage.implementation.ts
│ │ │ └── index.tsx
│ │ │
│ │ └── Modules/ # Módulos de negocio (Vertical Slices)
│ │ └── CreditCards/ # Ejemplo: Módulo de Tarjetas de Crédito
│ │ │
│ │ ├── Applications/ # Capa de Aplicación
│ │ │ └── UseCases/ # Casos de uso específicos
│ │ │ ├── GetAllCreditCards/ # ← NUEVO
│ │ │ │ └── GetAllCreditCardsUseCase.ts
│ │ │ ├── GetCreditCardById/ # ← NUEVO
│ │ │ │ └── GetCreditCardByIdUseCase.ts
│ │ │ ├── CreateCreditCard/ # ← NUEVO
│ │ │ │ └── CreateCreditCardUseCase.ts
│ │ │ ├── DeleteCreditCard/ # ← NUEVO
│ │ │ │ └── DeleteCreditCardUseCase.ts
│ │ │ ├── CreditCardUseCase.ts # (legacy)
│ │ │ └── index.tsx # ← REFACTORIZADO (DI)
│ │ │
│ │ ├── Domain/ # Capa de Dominio
│ │ │ ├── Dtos/ # Data Transfer Objects (validación estricta)
│ │ │ │ └── CreditCard.dto.ts
│ │ │ │
│ │ │ ├── Entities/ # Entidades del dominio
│ │ │ │ └── CreditCard.ts
│ │ │ │
│ │ │ ├── ValueObjects/ # ← NUEVO - Value Objects
│ │ │ │ ├── ProductNumber.ts
│ │ │ │ ├── Money.ts
│ │ │ │ └── ExpirationDate.ts
│ │ │ │
│ │ │ ├── Ports/ # ← NUEVO - Interfaces
│ │ │ │ └── ICreditCardRepository.ts
│ │ │ │
│ │ │ ├── Exceptions/ # ← NUEVO - Domain Exceptions
│ │ │ │ └── CreditCardErrors.ts
│ │ │ │
│ │ │ ├── Mappers/ # Mappers (DTO → Entity)
│ │ │ │ └── DtoToCreditCard.ts
│ │ │ │
│ │ │ └── Repository/ # (legacy - mover a Infrastructure)
│ │ │ └── CreditCard.repository.ts
│ │ │
│ │ └── Infrastructure/ # ← NUEVO - Adaptadores
│ │ └── Repositories/
│ │ ├── HttpCreditCardRepository.ts
│ │ └── MockCreditCardRepository.ts
│ │
│ ├── screens/ # Capa de Presentación
│ │ └── Auth/ # Ejemplo: Módulo de Autenticación
│ │ ├── index.tsx # Barrel export
│ │ │
│ │ ├── Login/ # Pantalla de Login
│ │ │ ├── Login.hook.ts # Custom hook con lógica
│ │ │ ├── Login.presenter.tsx # Componente presentacional
│ │ │ └── Login.style.ts # Estilos
│ │ │
│ │ ├── RecoverPassword/ # Pantalla de Recuperación
│ │ │ ├── RecoverPassword.hook.ts
│ │ │ ├── RecoverPassword.presenter.tsx
│ │ │ └── RecoverPassword.style.ts
│ │ │
│ │ └── components/ # Componentes específicos del módulo
│ │ ├── FormLogin/
│ │ │ ├── FormLogin.styles.ts
│ │ │ └── index.tsx
│ │ └── FormRecoverPassword/
│ │ ├── FormRecoverPassword.styles.ts
│ │ └── index.tsx
│ │
│ └── shared/ # Código compartido
│ ├── Components/ # Componentes reutilizables
│ │ └── Button/
│ │ ├── Button.styles.ts
│ │ └── index.tsx
│ │
│ ├── Types/ # ← NUEVO - Tipos compartidos
│ │ └── Result.ts # Result Pattern implementation
│ │
│ ├── Enums/ # Enumeraciones
│ │ ├── Storage.enum.ts
│ │ └── index.ts
│ │
│ └── Helpers/ # Funciones auxiliares
│ └── ZodValidator.ts
│
├── __tests__/ # ← AMPLIADO - Tests Unitarios
│ ├── ValueObjects/ # ← NUEVO
│ │ ├── ProductNumber.test.ts # 7 tests
│ │ └── Money.test.ts # 12 tests
│ │
│ ├── Repositories/ # ← NUEVO
│ │ └── MockCreditCardRepository.test.ts # 10 tests
│ │
│ └── App.test.tsx # Test original
│
├── .env.development # ← NUEVO - Variables de entorno dev
├── .env.staging # ← NUEVO - Variables de entorno staging
├── .env.production # ← NUEVO - Variables de entorno prod
├── .env.example # ← NUEVO - Plantilla de variables
├── .eslintrc.js # Configuración ESLint
├── .prettierrc.js # Configuración Prettier
├── .gitignore # ← ACTUALIZADO (excluye .env.*)
├── babel.config.js # ← ACTUALIZADO (alias @app)
├── tsconfig.json # ← ACTUALIZADO (alias @app, paths)
├── metro.config.js # Configuración Metro Bundler
├── jest.config.js # Configuración Jest
├── app.json # Configuración de la app
├── package.json # Dependencias y scripts
├── index.js # Punto de entrada (con Providers DI)
├── ARCHITECTURE_IMPROVEMENTS.md # ← NUEVO - Documentación detallada
└── README.md # Este archivo
Infrastructure/Contracts (Ports): Define las interfaces que deben implementar los adaptadores de infraestructura.
// Ejemplo: ICreditCardRepository.ts (Port)
export interface ICreditCardRepository {
getAll(): Promise<CreditCard[]>;
getById(productNumber: string): Promise<CreditCard>;
save(creditCard: CreditCard): Promise<void>;
delete(productNumber: string): Promise<void>;
}Infrastructure/Logger: Logger estructurado con niveles (DEBUG, INFO, WARN, ERROR) y contexto enriquecido.
Infrastructure/Http: Implementación concreta del cliente HTTP usando Axios.
Infrastructure/Storage: Implementación concreta del almacenamiento usando AsyncStorage.
Modules: Cada módulo representa una funcionalidad completa del negocio siguiendo Vertical Slicing.
Cada módulo sigue la estructura de Arquitectura Hexagonal:
Domain/Entities: Entidades del negocio (CreditCard).
Domain/ValueObjects: Objetos de valor inmutables con validación:
ProductNumber: Validación de 16 dígitos, máscara****-****-****-1234Money: Operaciones seguras con monedas (add, subtract, multiply)ExpirationDate: Validación MM/YYYY, verificación de expiración
Domain/Ports: Interfaces (contratos) que definen qué pueden hacer los adaptadores.
Domain/Exceptions: Excepciones específicas del dominio:
CreditCardNotFoundErrorInvalidProductNumberErrorCurrencyMismatchError- Y más...
Domain/Dtos: Data Transfer Objects con validación estricta usando Zod.
Applications/UseCases: Casos de uso específicos con una única responsabilidad (SRP):
GetAllCreditCardsUseCase: Obtiene todas las tarjetasGetCreditCardByIdUseCase: Busca por IDCreateCreditCardUseCase: Crea/actualiza tarjetaDeleteCreditCardUseCase: Elimina tarjeta
Cada UseCase:
- ✅ Recibe dependencias por constructor (DI)
- ✅ Retorna
Result<T, E>para manejo funcional de errores - ✅ Usa logging estructurado
- ✅ Maneja excepciones de dominio
Infrastructure/Repositories: Adaptadores que implementan los Ports:
HttpCreditCardRepository: Implementación con API realMockCreditCardRepository: Implementación para desarrollo/testing
Organización por características o flujos de usuario:
- Hook (.hook.ts): Lógica de la pantalla (estado, efectos, handlers)
- Presenter (.presenter.tsx): Componente de presentación (UI pura)
- Style (.style.ts): Estilos específicos de la pantalla
- components/: Componentes específicos de ese flujo
Código compartido entre módulos:
- Components: Componentes reutilizables (Button, Input, Card, etc.)
- Enums: Enumeraciones globales
- Helpers: Funciones auxiliares y utilidades
# Desarrollo
yarn start # Inicia Metro Bundler
yarn android # Ejecuta la app en Android
yarn ios # Ejecuta la app en iOS
# Calidad de Código
yarn lint # Ejecuta ESLint
yarn test # Ejecuta tests con Jest (30+ tests)
# TypeScript
npx tsc --noEmit # Verifica errores de TypeScript
# Mantenimiento
yarn upgrade # Actualiza dependencias
yarn outdated # Lista dependencias desactualizadasEl proyecto incluye 30+ tests unitarios que cubren:
# ProductNumber (7 tests)
✓ Validación de formato 16 dígitos
✓ Máscara de número ****-****-****-1234
✓ Últimos 4 dígitos
✓ Comparación de igualdad
# Money (12 tests)
✓ Operaciones aritméticas (add, subtract, multiply)
✓ Validación de monedas
✓ Prevención de cantidades negativas
✓ Comparaciones (greater, less, equals)# MockCreditCardRepository (10 tests)
✓ CRUD completo (getAll, getById, save, delete)
✓ Manejo de errores (NotFoundError)
✓ Método reset() para testingEjecutar tests:
yarn test # Ejecutar todos los tests
yarn test --watch # Modo watch
yarn test --coverage # Con cobertura📋 Reporte automático: Cada vez que ejecutas yarn test, se genera automáticamente TEST_RESULTS.md con un resumen completo de los resultados.
💡 Más info: Cómo funciona la generación de reportes
Con cobertura:
yarn test --coverageEl proyecto está configurado con path aliases para imports limpios:
// tsconfig.json & babel.config.js
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@app/*": ["src/app/*"], // ← NUEVO
"@core/*": ["src/app/core/*"],
"@enums/*": ["src/app/shared/Enums/*"],
"@components/*": ["src/app/shared/Components/*"],
"@helpers/*": ["src/app/shared/Helpers/*"]
}
}
}Uso:
// ❌ Antes
import { Button } from '../../../shared/Components/Button';
import { Result } from '../../../shared/Types/Result';
// ✅ Después
import { Button } from '@components/Button';
import { Result } from '@app/shared/Types/Result';El proyecto usa archivos .env para diferentes entornos:
# .env.development (desarrollo local)
NODE_ENV=development
API_BASE_URL=https://run.mocky.io/v3
USE_MOCK_REPOSITORY=true
ENABLE_LOGGING=true
# .env.staging (pruebas)
NODE_ENV=staging
API_BASE_URL=https://api.staging.com
USE_MOCK_REPOSITORY=false
ENABLE_LOGGING=true
# .env.production (producción)
NODE_ENV=production
API_BASE_URL=https://api.production.com
USE_MOCK_REPOSITORY=false
ENABLE_LOGGING=falseNota: Los archivos .env.* están en .gitignore. Usa .env.example como plantilla.
Manejo funcional de errores sin try-catch excesivos:
// En un componente
const {getAllCreditCards} = useCreditCardUseCases();
const loadCards = async () => {
const result = await getAllCreditCards.execute();
if (result.isSuccess) {
const cards = result.getValue();
setCards(cards);
} else {
const error = result.getError();
console.error(error.message);
}
};
// Métodos funcionales
result.map(cards => cards.length); // Transforma el valor
result.flatMap(cards => otherResult); // Encadena operaciones
result.onSuccess(cards => console.log); // Callback si exitoso
result.onFailure(error => console.error); // Callback si fallaLos UseCases reciben dependencias por constructor:
// UseCases/index.tsx
const repository: ICreditCardRepository = new MockCreditCardRepository();
// O cambiar a: new HttpCreditCardRepository(httpImpl);
const useCases = {
getAllCreditCards: new GetAllCreditCardsUseCase(repository, logger),
getCreditCardById: new GetCreditCardByIdUseCase(repository, logger),
createCreditCard: new CreateCreditCardUseCase(repository, logger),
deleteCreditCard: new DeleteCreditCardUseCase(repository, logger),
};Beneficios:
- ✅ Fácil cambiar entre Mock y HTTP
- ✅ Testing sin dependencias externas
- ✅ Trabajo offline habilitado
Este proyecto tiene la New Architecture de React Native habilitada por defecto:
Android (android/gradle.properties):
newArchEnabled=trueiOS (ios/RNTemplateHexagonal/Info.plist):
<key>RCTNewArchEnabled</key>
<true/>Configuración personalizada para React Native 0.82.0:
// .eslintrc.js
module.exports = {
root: true,
extends: '@react-native',
rules: {
'@react-native/no-deep-imports': 'off', // Deshabilitada por incompatibilidad
},
};El proyecto usa react-native-safe-area-context en lugar del SafeAreaView deprecado de React Native:
// index.js - Punto de entrada
import {SafeAreaProvider} from 'react-native-safe-area-context';
function AppWithProvider() {
return (
<SafeAreaProvider>
<App />
</SafeAreaProvider>
);
}// En componentes
import {SafeAreaView} from 'react-native-safe-area-context';
function MyScreen() {
return (
<SafeAreaView>
{/* Contenido */}
</SafeAreaView>
);
}Error: SDK location not found
echo "sdk.dir=$ANDROID_HOME" > android/local.propertiesError: Gradle daemon
cd android
./gradlew clean
cd ..Error: Port 8081 already in use
lsof -ti:8081 | xargs kill -9Error: Pod install fails
cd ios
pod deintegrate
pod install
cd ..Error: Xcode build fails
cd ios
xcodebuild clean
cd ..Error: Metro bundler cache
yarn start --reset-cacheError: Node modules
rm -rf node_modules yarn.lock
yarn installSi no puedes solucionar un problema, consulta la página de Troubleshooting de React Native.
- React Native Website - Documentación oficial
- Getting Started - Setup del entorno
- Learn the Basics - Tour guiado de los básicos
- Blog - Posts oficiales del blog
- GitHub Repository - Repositorio oficial
- Clean Architecture - Por Uncle Bob
- Hexagonal Architecture - Por Alistair Cockburn
- SOLID Principles - Principios de diseño
- Result Pattern - Manejo funcional de errores
- ARCHITECTURE_IMPROVEMENTS.md - 📚 Documentación detallada de mejoras (400+ líneas)
- TypeScript Handbook - Documentación oficial
- React TypeScript Cheatsheet - Guía práctica
Este proyecto aplica completamente los 5 principios SOLID:
| Principio | Implementación | Ejemplo |
|---|---|---|
| SRP | Cada UseCase una responsabilidad | GetAllCreditCardsUseCase solo obtiene |
| OCP | Extensible sin modificar | Agregar UpdateCreditCardUseCase sin tocar existentes |
| LSP | Implementaciones intercambiables | MockRepository HttpRepository |
| ISP | Interfaces específicas | ICreditCardRepository, ILogger |
| DIP | Dependencias de abstracciones | UseCases dependen de ICreditCardRepository |
| Métrica | Valor |
|---|---|
| Tests Unitarios | 30+ ✅ |
| Cobertura de Tests | Value Objects + Repositories |
| Value Objects | 3 (ProductNumber, Money, ExpirationDate) |
| Domain Exceptions | 7 específicas |
| UseCases | 4 con SRP |
| Repositorios | 2 (Mock + HTTP) |
| Logging | Estructurado con 4 niveles |
| Lines of Code | ~3,000+ |
- Ejecutar tests:
yarn test - Verificar compilación:
npx tsc --noEmit - Probar app en dispositivo
- Implementar Domain Events
- Agregar React Query para cache
- Crear más tests de integración
- Implementar navegación tipada
- Conectar a API real
- Implementar autenticación
- Agregar más módulos (Users, Transactions)
- Setup CI/CD con tests automáticos
- Cobertura de tests >80%
Las contribuciones son bienvenidas. Por favor:
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abre un Pull Request
- ✅ Escribe tests para nuevas funcionalidades
- ✅ Sigue los principios SOLID
- ✅ Usa Value Objects cuando sea apropiado
- ✅ Implementa Result Pattern para errores
- ✅ Documenta con JSDoc
- ✅ Mantén la separación de capas
Este proyecto es privado.
- Raico Acosta - @raicoacosta
⭐ Si este template te resultó útil, considera darle una estrella en GitHub!