ixiclinicDocs
DesarrolladoresApps del monorepo

API

Backend REST de ixiclinic — Fastify 5, Drizzle ORM, PostgreSQL y Zod 4. Patrón de módulos, cadena de plugins, tiempo real y despliegue.

El API (apps/api) es el backend REST multi-tenant de ixiclinic: todo lo demás (admin, console, portal, lab-site, mobile) consume sus endpoints. Es la única pieza con acceso directo a la base de datos.

StackFastify 5, Drizzle ORM, PostgreSQL, Zod 4
Puerto local5000
Producciónapi.ixiclinic.com (VPS, Nginx → Docker)
Paquete@ixiclinic/api
Docs OpenAPI/docs (Scalar UI)

Estructura

El bootstrap vive en apps/api/src/index.ts (arranca el servidor, ejecuta ensureNcfFunction() y monta Socket.IO). La construcción de la instancia Fastify está en apps/api/src/app.ts (buildApp()), que registra plugins y rutas. La configuración validada con Zod está en apps/api/src/config/env.ts.

Patrón de módulos (4 archivos)

Cada dominio vive en apps/api/src/modules/<dominio>/ y sigue la misma estructura de cuatro archivos:

ArchivoResponsabilidad
routes.tsRegistro de rutas en Fastify y preHandler (auth/RBAC).
handlers.tsRecepción de la petición, validación y formato de respuesta.
service.tsLógica de negocio y consultas a la base de datos (Drizzle).
schemas.tsEsquemas de validación Zod (entrada y salida).

Para crear uno nuevo paso a paso, ver Añadir un módulo al API.

Excepciones a la estructura base:

  • instruments/ tiene un subdirectorio parsers/ con parsers de datos de instrumentos de laboratorio: astm.ts, csv.ts, hl7.ts, xml.ts.
  • appointments/ añade reminder-service.ts y appointment-notifications.ts.

Módulos (45)

Los módulos se agrupan por categoría. Todos viven en apps/api/src/modules/.

Núcleo y operación del laboratorio

auth, impersonation, health, tenants, patients, catalog, orders, results, search, billing, ecf, reception, dashboard, inventory, settings, qc, uploads, cash, lookup, companies, doctors, samples, instruments, queue, notifications, appointments, prescriptions, printing, chat, templates.

Nota: La lógica fiscal DGII (e-CF) es un módulo del API (ecf), no vive en el admin. El admin solo expone la UI y llama a estos endpoints vía server actions.

Clínicos

consultations, procedures, cardiology, encounters, programs, activities. Cubren encuentros estructurados, procedimientos, cardiología y los programas crónicos de seguros (ARS).

Portal del cliente (sin token de tenant)

portal, client-auth, client-portal, client-company. Atienden al lab-site público y al portal del paciente/empresa. Sus rutas se saltan el middleware de auth de tenant.

SaaS (superadmin)

saas-auth, demos, subscriptions, saas, organizations. Sirven a la console interna bajo /api/saas/* y exigen el preHandler requireSuperadmin (excepto POST /api/saas/demos, que es público y lo llama la landing).

Cadena de plugins

buildApp() registra los plugins en este orden exacto (apps/api/src/app.ts):

  1. @fastify/swagger — genera el OpenAPI.
  2. @fastify/multipart — subidas, límite de 5 MB.
  3. @fastify/cors — permite *.ixiclinic.com, los orígenes de CORS_ORIGINS y localhost en dev.
  4. @fastify/helmet — cabeceras de seguridad (CSP desactivado).
  5. @fastify/rate-limit500 peticiones/min por IP.
  6. errorHandler — captura ZodError y formatea los errores de validación con la ruta del campo.
  7. authPlugin — verifica el JWT (Bearer) salvo en rutas públicas.
  8. tenantScopePlugin — inyecta el contexto de tenant en cada petición.
  9. @scalar/fastify-api-reference — UI de docs en /docs.
  10. @fastify/schedule + schedulerPlugin — tareas en segundo plano.
  11. Todas las rutas de los módulos.

Los plugins viven en apps/api/src/plugins/: auth.ts, tenant-scope.ts, error-handler.ts, scheduler.ts, socket.ts, rbac.ts / rbac-config.ts, require-superadmin.ts, client-auth.ts, instrument-auth.ts, bridge-auth.ts.

Rutas públicas (sin token)

El authPlugin (apps/api/src/plugins/auth.ts) deja pasar sin JWT estos prefijos:

/api/auth/login   /api/auth/register   /api/auth/refresh
/api/portal/      /api/health          /docs
/api/saas/auth/   /api/client/auth/    /api/client/
/api/queue/board/ /api/queue/patient/
/api/webhooks/    /api/bridge/

Y estas rutas concretas por método:

  • POST /api/saas/demos (formulario de demo de la landing).
  • POST /api/instruments/{id}/push (datos entrantes de instrumentos).
  • POST /api/queue/kiosks/{id}/ticket y .../appointment-ticket (kiosko).
  • GET /api/queue/kiosks/{id}/config (configuración del kiosko).

Base de datos

Drizzle ORM sobre PostgreSQL. Los esquemas viven en apps/api/src/db/schema/ (25 archivos por dominio: tenants, branches, patients, clients, catalog, orders, results, inventory, billing, insurance, qc, dgii, audit, saas, appointments, instruments, notifications, queue, prescriptions, encounters, programs, activities, templates, printing, chat). Las migraciones salen a apps/api/src/db/migrations. Detalle completo en Base de datos.

Comandos (desde apps/api):

pnpm db:generate   # genera migraciones desde el schema
pnpm db:migrate    # aplica migraciones
pnpm db:push       # empuja el schema directo (solo dev)
pnpm db:studio     # abre Drizzle Studio
pnpm db:seed       # datos de demo

Tiempo real (Socket.IO)

Socket.IO se inicializa sobre el servidor HTTP en index.ts (initSocket, definido en apps/api/src/plugins/socket.ts). Usa varios namespaces: /queue y /screen (turnos), /kiosk, /notifications, /chat (chat interno autenticado, con salas por conversación, usuario y tenant) y /bridge (trabajos hacia ixiclinic Connect en la LAN del cliente).

Tareas programadas (scheduler)

schedulerPlugin (toad-scheduler vía @fastify/schedule) registra trabajos recurrentes:

TrabajoFrecuencia
Procesar recordatorios de citascada 5 min
Detectar no-showscada 10 min
Cerrar cajas obsoletas + liberar turnoscada 15 min
Resumen diariocron 0 7 * * *

Los envíos de recordatorios usan apps/api/src/lib/email-reminders.ts y apps/api/src/lib/whatsapp.ts. Otros helpers de apps/api/src/lib/: jwt.ts, password.ts, pagination.ts, audit.ts, tenant-seed.ts, y los generadores de impresión escpos/ (recibos térmicos) y labels/ (etiquetas TSPL).

OpenAPI / Scalar

La documentación interactiva del API está en /docs (Scalar UI), generada automáticamente desde los esquemas registrados con @fastify/swagger.

Build y despliegue

build compila con tsc a dist/; start ejecuta node dist/migrate.js && node dist/index.js (las migraciones corren al arrancar). En producción se empaqueta con un Dockerfile multi-stage (node:22-alpine, usuario no-root, EXPOSE 5000, healthcheck contra /api/health). El despliegue corre en el VPS con Docker Compose. Ver Operaciones.

On this page