Saltar al contenido principal

Estructura de Módulo

Cada módulo de API sigue una estructura interna consistente con controladores, repositorios, modelos y ayudantes. Comprender este diseño permite navegar fácilmente por la base de código y agregar nuevas funcionalidades a cualquier módulo.

Antes de Comenzar

Diseño de Directorio

Cada módulo vive bajo src/modules/{name}/ y contiene cuatro directorios:

src/modules/{name}/
├── controllers/ ← Controladores de ruta (puntos de conexión Express)
├── repositories/ ← Capa de acceso a datos (SQL directo)
├── models/ ← Interfaces de TypeScript y tipos
└── helpers/ ← Lógica de negocio específica del módulo

Por ejemplo, el módulo de membresía:

src/modules/membership/
├── controllers/
│ ├── PersonController.ts
│ ├── GroupController.ts
│ └── ...
├── repositories/
│ ├── PersonRepository.ts
│ ├── GroupRepository.ts
│ └── ...
├── models/
│ ├── Person.ts
│ ├── Group.ts
│ └── ...
└── helpers/
└── ...

Controladores

Los controladores definen las rutas de API para un módulo. Extienden CustomBaseController de @churchapps/apihelper y utilizan decoradores de Inversify para registro de rutas.

import { controller, httpGet, httpPost } from "inversify-express-utils";
import { CustomBaseController } from "@churchapps/apihelper";

@controller("/people")
export class PersonController extends CustomBaseController {

@httpGet("/")
public async loadAll() {
return this.actionWrapper(async (au) => {
// au = contexto de usuario autenticado
au.checkAccess("People", "View");
const repos = RepositoryManager.getRepositories<MembershipRepositories>("membership");
return repos.person.loadByChurchId(au.churchId);
});
}

@httpPost("/")
public async save() {
return this.actionWrapper(async (au) => {
au.checkAccess("People", "Edit");
const data = this.request.body;
// ... lógica de guardar
});
}
}

Decoradores de Ruta

DecoradorMétodo HTTP
@httpGet("/path")GET
@httpPost("/path")POST
@httpPut("/path")PUT
@httpPatch("/path")PATCH
@httpDelete("/path")DELETE

El decorador @controller("/base") establece la ruta base para todas las rutas en el controlador.

Repositorios

Los repositorios manejan todas las operaciones de base de datos utilizando SQL directo a través de DB.query(). No hay ORM -- escribe SQL directamente.

export class PersonRepository {
public async loadByChurchId(churchId: string) {
return DB.query("SELECT * FROM people WHERE churchId=?", [churchId]);
}

public async save(person: Person) {
// Lógica de INSERT o UPDATE
}
}

Acceda a repositorios a través de RepositoryManager:

const repos = RepositoryManager.getRepositories<MembershipRepositories>("membership");
const people = await repos.person.loadByChurchId(churchId);

Autenticación y Autorización

Autenticación JWT

Todas las solicitudes se autentican a través de tokens JWT manejados por CustomAuthProvider. El token se valida automáticamente y el contexto de usuario autenticado (au) está disponible en cada acción del controlador.

Verificaciones de Permiso

Use au.checkAccess() para verificar que el usuario actual tiene el permiso requerido:

au.checkAccess("People", "View");    // Acceso de lectura
au.checkAccess("People", "Edit"); // Acceso de escritura

Si al usuario le falta el permiso requerido, se devuelve automáticamente una respuesta de error.

aviso

Siempre llame a au.checkAccess() antes de realizar cualquier operación de datos. Nunca omita verificaciones de permisos, incluso para puntos de conexión aparentemente de solo lectura.

Configuración de Entorno

La clase Environment maneja la configuración entre entornos:

  • Desarrollo local: Lee desde el archivo .env en la raíz del proyecto
  • Entornos desplegados: Lee desde AWS SSM Parameter Store
// Acceder a variables de entorno
const dbConnection = Environment.membershipDb;
const jwtSecret = Environment.jwtSecret;

Esta abstracción significa que su código no necesita saber de dónde proviene la configuración.

Funciones de Lambda

Cuando se despliega en AWS, la API se ejecuta como cuatro funciones de Lambda:

FunciónPropósito
webManeja todas las solicitudes de API REST HTTP
socketGestiona conexiones de WebSocket para características en tiempo real
timer15MinProgramada cada 15 minutos para notificaciones por correo
timerMidnightProgramada diariamente para correos resumen y mantenimiento
info

Localmente, la función web se ejecuta en el puerto 8084 y la función socket se ejecuta en el puerto 8087. Las funciones del temporizador se pueden activar manualmente durante el desarrollo.

Artículos Relacionados

  • Base de Datos -- Cadenas de conexión, scripts de esquema y patrones de acceso a datos
  • Configuración Local de API -- Guía completa paso a paso de configuración
  • ApiHelper -- La biblioteca compartida que proporciona CustomBaseController y middleware de autenticación