Backend RESTful empresarial de alto rendimiento para el sistema de gestion hotelera Nicabliss, construido con Node.js, Express, TypeScript en modo estricto, seguridad JWT, hashing con Bcrypt, persistencia relacional distribuida en el Edge con Turso Web (LibSQL / SQLite) y una arquitectura en capas limpia, modular y desacoplada.
- Vision General del Sistema
- Stack Tecnologico y Dependencias
- Estructura del Proyecto y Arquitectura
- Instalacion y Puesta en Marcha
- Variables de Entorno
- Credenciales y Datos de Prueba
- Documentacion Tecnica de la API (Endpoints)
- Suite de Pruebas Automatizadas (QA)
- Seguridad y Politicas
- Base de Datos Turso Web (LibSQL) y Diagrama ER
- Despliegue en Vercel (Arquitectura Serverless)
Nicabliss API centraliza y automatiza todas las operaciones diarias de un hotel moderno:
- Recepcion: Registro de huespedes, check-in, check-out y validacion de consistencia de fechas.
- Cuentas y Facturacion: Cargos por habitacion, abonos parciales, liquidacion total y calculo dinamico de saldos.
- Cocina y Room Service: Comandas de alimentos, calculo de importes y ciclo de preparacion.
- Lavanderia: Conteo por tipo de prenda, tarifa unitaria automatica ($0.50) y seguimiento de entrega.
- Caja Chica y Turnos: Apertura de caja con fondo inicial, control de ingresos/egresos, arqueo de efectivo con calculo de diferencia (sobrante/faltante) y cierre de turno.
- Dashboard en Tiempo Real: Agregacion instantanea de ingresos del dia, pedidos pendientes y ocupacion.
| Tecnologia / Libreria | Version | Proposito en el Proyecto |
|---|---|---|
| Node.js | >= 20.x (Probado en v24.19.0) | Entorno de ejecucion en servidor. |
| TypeScript | ^5.8.2 | Tipado estatico estricto, interfaces y validacion en tiempo de compilacion. |
| Express | ^4.21.2 | Framework HTTP rapido y minimalista para el diseno de APIs RESTful. |
| jsonwebtoken | ^9.0.2 | Generacion y verificacion de tokens Bearer firmados criptograficamente. |
| bcryptjs | ^3.0.3 | Hashing seguro de contrasenas con factor de coste de 10 salt rounds. |
| helmet | ^8.0.0 | Configuracion segura de cabeceras HTTP (CSP, noSniff, xssFilter). |
| cors | ^2.8.5 | Control de acceso HTTP entre origenes (Frontend localhost:5173). |
| dotenv | ^16.4.7 | Inyeccion y tipado de variables de entorno desde archivos .env. |
| @libsql/client | ^0.18.0 | Cliente oficial de Turso para conexiones LibSQL/SQLite en el Edge sin binarios C++. |
| tsx | ^4.19.3 | Ejecucion directa de TypeScript en desarrollo y runner de pruebas ultrarrapido. |
El proyecto esta disenado bajo una Arquitectura en Capas Limpias (Layered Architecture) para garantizar separacion de responsabilidades y maxima facilidad de lectura:
nicabliss_api/
|-- .env # Variables de entorno activas (ignorado por git)
|-- .env.example # Plantilla de variables de entorno para despliegue
|-- .gitignore # Reglas de exclusion para git (node_modules, dist, .env)
|-- package.json # Definicion de dependencias, metadatos y scripts
|-- tsconfig.json # Configuracion estricta de TypeScript (ES2022 / NodeNext)
|-- README.md # Documentacion tecnica completa
|-- dist/ # Codigo JavaScript compilado para produccion
|-- tests/ # Suite de pruebas automatizadas (QA)
| |-- unit/ # Pruebas unitarias de servicios y modelos de negocio
| | |-- auth.service.test.ts
| | |-- guest.service.test.ts
| | |-- billing.service.test.ts
| | |-- food-order.service.test.ts
| | |-- laundry.service.test.ts
| | |-- cash.service.test.ts
| | `-- dashboard.service.test.ts
| `-- integration/ # Pruebas de integracion de la API HTTP (E2E)
| `-- api.test.ts
`-- src/
|-- config/ # Configuracion del entorno (env.ts con soporte Turso)
|-- db/ # Capa de base de datos Turso LibSQL
| |-- client.ts # Cliente singleton de conexion a Turso (@libsql/client)
| |-- schema.sql # Definicion DDL relacional, constraints e indices
| |-- migrate.ts # Ejecutor automatizado de migraciones DDL
| `-- seed.ts # Semillero con datos iniciales (admin, huespedes, turnos)
|-- models/ # Modelos de datos del dominio y tipos de entidades
| |-- user.model.ts # Usuario, credenciales y roles
| |-- guest.model.ts # Huesped y estancias
| |-- billing.model.ts # Cuentas, totales y estados de cobro
| |-- food-order.model.ts # Ordenes de alimentos
| |-- laundry.model.ts # Solicitudes de lavanderia y catalogo de prendas
| `-- cash.model.ts # Turnos de caja y movimientos
|-- dtos/ # Contratos de Datos (Data Transfer Objects)
| |-- auth.dto.ts
| |-- user.dto.ts
| |-- guest.dto.ts
| |-- billing.dto.ts
| |-- food-order.dto.ts
| |-- laundry.dto.ts
| `-- cash.dto.ts
|-- repositories/ # Capa de Persistencia Relacional en Turso (LibSQL)
| |-- user.repository.ts
| |-- guest.repository.ts
| |-- billing.repository.ts
| |-- food-order.repository.ts
| |-- laundry.repository.ts
| `-- cash.repository.ts
|-- services/ # Logica de negocio, reglas y validaciones
| |-- auth.service.ts
| |-- user.service.ts
| |-- guest.service.ts
| |-- billing.service.ts
| |-- food-order.service.ts
| |-- laundry.service.ts
| |-- cash.service.ts
| `-- dashboard.service.ts
|-- controllers/ # Manejadores de peticion (Request) y respuesta (Response)
| |-- auth.controller.ts
| |-- user.controller.ts
| |-- guest.controller.ts
| |-- billing.controller.ts
| |-- food-order.controller.ts
| |-- laundry.controller.ts
| |-- cash.controller.ts
| `-- dashboard.controller.ts
|-- routes/ # Definicion de rutas y endpoints Express
| |-- auth.routes.ts
| |-- user.routes.ts
| |-- guest.routes.ts
| |-- billing.routes.ts
| |-- food-order.routes.ts
| |-- laundry.routes.ts
| |-- cash.routes.ts
| |-- dashboard.routes.ts
| `-- index.ts # Enrutador centralizado montado en /api/v1
|-- middlewares/ # Filtros de seguridad y manejo global
| |-- auth.middleware.ts # Validacion de Bearer Token JWT
| |-- role.middleware.ts # Autorizacion RBAC (ADMIN, RECEPTIONIST)
| |-- error.middleware.ts # Capturador central de excepciones con codigos HTTP
| `-- logger.middleware.ts # Registro en consola de tiempo y status de peticiones
|-- utils/ # Utilidades transversales
| |-- hasher.ts # Hashing con Bcrypt (hash y hashSync)
| |-- jwt.ts # Firma y verificacion de tokens
| `-- logger.ts # Formateador de consola con timestamp
|-- app.ts # Ensamblador de la aplicacion Express
`-- server.ts # Inicializacion en puerto 4000 y Graceful Shutdown
- Node.js version 20 o superior.
- npm version 9 o superior.
cd C:\Users\joshu\Downloads\nicabliss_apinpm installEl proyecto incluye un archivo .env preconfigurado. Si deseas crear uno nuevo:
cp .env.example .envInicia la API con recarga en caliente utilizando tsx:
npm run devCompila el codigo TypeScript a JavaScript optimizado en dist/:
npm run build
npm startArchivo .env:
| Variable | Tipo | Valor Predeterminado | Descripcion |
|---|---|---|---|
| PORT | Numero | 4000 | Puerto TCP en el que escuchara el servidor Express. |
| NODE_ENV | String | development | Entorno de ejecucion (development / production). |
| JWT_SECRET | String | Clave secreta | Clave simetrica utilizada para firmar los tokens JWT. |
| JWT_EXPIRES_IN | String | 8h | Tiempo de vida de los tokens de sesion. |
| CORS_ORIGIN | String | http://localhost:5173 | Origenes permitidos separados por comas para el Frontend. |
| TURSO_DATABASE_URL | String | libsql://...turso.io | URL de conexion a la base de datos distribuida en Turso. |
| TURSO_AUTH_TOKEN | String | Token JWT firmado | Token de autenticacion con permisos rw para Turso Cloud. |
La API se inicializa en memoria con un usuario administrador precargado con contrasena hasheada:
- Usuario: admin
- Contrasena: 12345
- Rol: ADMIN
Todas las rutas (excepto /health y /api/v1/auth/login) requieren la cabecera HTTP:
Authorization: Bearer <TU_TOKEN_JWT>Todas las respuestas de la API siguen un formato predecible:
Exito:
{
"success": true,
"data": { ... }
}Error:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Descripcion clara del error"
},
"timestamp": "2026-10-20T14:00:00.000Z"
}Verifica que el servicio este activo.
- Acceso: Publico
- Respuesta (200 OK):
{
"status": "ok",
"system": "Nicabliss Hotel Management API",
"environment": "development",
"timestamp": "2026-10-20T14:15:00.000Z"
}Inicia sesion y obtiene un token JWT firmado.
- Acceso: Publico
- Body:
{
"usuario": "admin",
"password": "12345"
}- Respuesta (200 OK):
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "usr_admin_001",
"username": "admin",
"email": "admin@nicabliss.com",
"fullName": "Administrador Nicabliss",
"role": "ADMIN",
"createdAt": "2026-10-20T08:00:00.000Z"
}
}
}Registra un nuevo usuario en el sistema.
- Acceso: Protegido (Requiere rol ADMIN)
- Body:
{
"username": "recepcion1",
"email": "recepcion@nicabliss.com",
"password": "Password123",
"fullName": "Juan Recepcion",
"role": "RECEPTIONIST"
}- Respuesta (201 Created): Retorna el objeto del usuario creado sin la contrasena.
Retorna los datos del usuario autenticado actual.
- Acceso: Protegido
Todos los endpoints bajo /api/v1/users requieren obligatoriamente autenticación y rol de Administrador (authMiddleware + requireRole("ADMIN")).
Retorna la lista completa de usuarios del sistema con sus roles y perfiles (omitiendo estrictamente el hash de contraseñas).
- Acceso: Protegido (Solo ADMIN)
- Respuesta (200 OK):
{
"success": true,
"count": 2,
"data": [
{
"id": "usr_admin_001",
"username": "admin",
"email": "admin@nicabliss.com",
"fullName": "Administrador Nicabliss",
"role": "ADMIN",
"createdAt": "2026-10-20T08:00:00.000Z"
}
]
}Obtiene los detalles y rol de un usuario específico mediante su identificador único.
- Acceso: Protegido (Solo ADMIN)
Crea un nuevo usuario en la base de datos asignándole su rol (ADMIN, RECEPTIONIST, o STAFF).
- Acceso: Protegido (Solo ADMIN)
- Body:
{
"username": "marta_staff",
"email": "marta@nicabliss.com",
"password": "PasswordSegura123",
"fullName": "Marta Mantenimiento",
"role": "STAFF"
}- Respuesta (201 Created): Retorna el usuario creado con ID único.
Actualiza la información de un usuario (rol, nombre, correo o contraseña).
- Acceso: Protegido (Solo ADMIN)
- Body:
{
"fullName": "Marta Jefa de Turno",
"role": "RECEPTIONIST"
}- Respuesta (200 OK): Retorna el usuario actualizado.
- Regla de Protección de Integridad: Se prohíbe degradar o modificar el rol del administrador principal (
admin/usr_admin_001).
Elimina de forma permanente un usuario del sistema.
- Acceso: Protegido (Solo ADMIN)
- Respuesta (200 OK):
{
"success": true,
"message": "Usuario con ID 'usr_123' eliminado correctamente"
}- Senior Security Guardrails:
- Anti-Autoeliminación: Un administrador no puede eliminar su propia cuenta activa (
req.user.sub === id). - Protección del Root Admin: El usuario administrador principal no puede ser eliminado.
- Anti-Autoeliminación: Un administrador no puede eliminar su propia cuenta activa (
Retorna las estadisticas agregadas del hotel en tiempo real.
- Acceso: Protegido
- Respuesta (200 OK):
{
"success": true,
"data": {
"stats": [
{ "label": "Ingresos del dia", "value": "$ 43.00", "detail": "Pagos registrados", "code": "revenue", "className": "stat-green" },
{ "label": "Cuentas abiertas", "value": "2", "detail": "Huespedes con saldo activo", "code": "accounts", "className": "stat-blue" },
{ "label": "Pedidos pendientes", "value": "2", "detail": "Solicitudes por atender", "code": "orders", "className": "stat-orange" },
{ "label": "Lavanderia pendiente", "value": "1", "detail": "Solicitudes en proceso", "code": "laundry", "className": "stat-purple" }
],
"activeStays": 2,
"cashRegisterActive": true,
"recentTransactions": [ ... ]
}
}Lista los huespedes registrados. Soporta busqueda con ?search=.
- Query Params: ?search=carlos (opcional)
- Acceso: Protegido
Obtiene los detalles de un huesped especifico.
Registra un nuevo huesped.
- Body:
{
"nombre": "Elena Rivas",
"documento": "001-120499-0004D",
"habitacion": "Habitacion 05",
"entrada": "2026-10-21",
"salida": "2026-10-24",
"estado": "Activo"
}- Regla de Negocio: Falla con 400 VALIDATION_ERROR si la fecha de salida es anterior a entrada.
Actualiza los datos completos de un huesped (nombre, documento, habitacion, fechas o estado).
- Body:
{
"nombre": "Maria Gonzalez",
"habitacion": "Habitacion 02",
"salida": "2026-10-22"
}Actualiza el estado de una estancia (Activo | Finalizado | Reservado).
Elimina el registro de un huesped del sistema.
- Respuesta (200 OK):
{ "success": true, "message": "Huesped con id 1 eliminado correctamente" }
Obtiene todas las cuentas, el total facturado, cobrado y saldo global pendiente.
- Respuesta (200 OK):
{
"success": true,
"cuentas": [ ... ],
"resumen": {
"totalFacturado": 60.5,
"totalCobrado": 43.0,
"saldoPendiente": 17.5
}
}Crea una nueva cuenta o cargo para una habitacion.
- Body:
{
"huesped": "Elena Rivas",
"habitacion": "Habitacion 05",
"concepto": "Hospedaje 3 noches",
"total": 120.0
}Actualiza los datos o el total de una cuenta de cobro, recalculando automaticamente el saldo y el estado.
- Body:
{
"concepto": "Estancia extendida a 4 noches",
"total": 160.0
}- Regla de Negocio: El total no puede ser inferior a los abonos ya registrados.
Registra un abono a una cuenta existente.
- Body:
{
"monto": 50.0
}- Regla de Negocio: Si el monto abonado completa la deuda, el estado cambia automaticamente a Pagado. Si es parcial, a Parcial. Rechaza con error 400 si el monto supera el saldo pendiente.
Elimina una cuenta de cobro pendiente.
- Regla Contable: Solo permite eliminar cuentas sin abonos o pagos registrados (
pagado === 0). Si tiene pagos, rechaza con 400 VALIDATION_ERROR para proteger la auditoria fiscal.
Lista los pedidos de restaurante/cocina.
Crea una nueva comanda de alimentos.
- Body:
{
"huesped": "Maria Gonzalez",
"habitacion": "Habitacion 01",
"productos": "2 desayunos tipicos + 1 jugo de naranja",
"total": 14.0
}- Nota: Genera automaticamente un codigo de comanda correlativo unico (ej: #PED-582) con estado inicial Pendiente.
Actualiza los productos, total o destino de la comanda.
- Body:
{
"productos": "2 desayunos tipicos + 2 jugos naturales",
"total": 17.0
}Actualiza el estado de la comanda (Pendiente | En preparacion | En camino | Entregado | Cancelado).
Elimina una comanda del sistema.
Lista las solicitudes de lavanderia.
Crea una nueva solicitud con desglose de prendas.
- Body:
{
"huesped": "Carlos Mendoza",
"habitacion": "Habitacion 04",
"prendas": [
{ "tipo": "Camisa", "cantidad": 3 },
{ "tipo": "Pantalon", "cantidad": 2 },
{ "tipo": "Toalla", "cantidad": 1 }
],
"observaciones": "Planchar con almidon suave"
}- Regla de Negocio: La API calcula automaticamente el total de prendas (6 prendas) y el importe exacto basado en la tarifa de $0.50 por prenda ($3.00 en total).
Actualiza la orden de lavanderia (prendas, observaciones o destino). Si se modifican las prendas, recalcula automaticamente el total y conteo a $0.50 por prenda.
Actualiza el estado (Pendiente | En proceso | Listo | Entregado | Cancelado).
Elimina una orden de lavanderia del sistema.
Consulta los datos de la sesion de caja activa actual. Retorna data: null si la caja esta cerrada.
Abre un nuevo turno de caja con fondo inicial.
- Body:
{
"responsable": "Juan Recepcionista",
"fondoInicial": 100.0
}- Regla de Negocio: Impide abrir un nuevo turno si ya existe una sesion abierta (409 CONFLICT).
Registra un movimiento (ingreso o gasto operativo).
- Body:
{
"tipo": "Salida",
"concepto": "Gasto operativo",
"descripcion": "Compra de cafe y azucar para recepcion",
"metodo": "Efectivo",
"monto": 12.0
}- Regla de Negocio: Impide que una salida en efectivo supere el monto disponible en caja (400 VALIDATION_ERROR).
Realiza el arqueo y cierre del turno.
- Body:
{
"efectivoContado": 128.0,
"observaciones": "Turno cerrado sin incidencias"
}- Regla de Negocio: Calcula automaticamente la diferencia (efectivoContado - efectivoEsperado), archiva la sesion en el historial y libera la caja para el siguiente turno.
Lista el historial de todos los cierres de caja realizados.
El proyecto incluye 44 pruebas automatizadas que garantizan que ningun cambio rompa la logica del negocio ni las operaciones CRUD:
Para correr las pruebas:
npm test- auth.service.test.ts (5 pruebas): Login exitoso, rechazo por contrasena erronea, rechazo por usuario inexistente, hasheo de contrasenas y deteccion de duplicados.
- guest.service.test.ts (7 pruebas): Listado, filtrado, creacion, validacion de fechas de salida, actualizacion de estancia, actualizacion completa (PUT) y eliminacion (DELETE).
- billing.service.test.ts (8 pruebas): Totales iniciales, creacion de cuenta, abono parcial, liquidacion total, rechazo de sobrepagos, actualizacion (PUT) con recalculo de saldos, proteccion contable contra borrado de cuentas con abonos y eliminacion limpia de cuentas sin abono (DELETE).
- food-order.service.test.ts (5 pruebas): Creacion con correlativo, ciclo de estados de comanda, edicion (PUT) y eliminacion (DELETE).
- laundry.service.test.ts (5 pruebas): Tarificacion automatica ($0.50/prenda), cambio de estado, rechazo de solicitudes sin prendas, edicion de lote con recalculo automatico (PUT) y eliminacion (DELETE).
- cash.service.test.ts (5 pruebas): Apertura, bloqueo de turnos dobles, movimientos, limite de egresos en efectivo, arqueo y diferencia de caja.
- dashboard.service.test.ts (1 prueba): Agregacion simultanea de metricas multi-repositorio.
- api.test.ts (8 pruebas E2E): Health check, login HTTP, rechazo de rutas sin token, acceso con Bearer token, listado de huespedes, actualizacion HTTP (PUT), eliminacion HTTP (DELETE) y respuestas semanticas 404.
- Proteccion de Contrasenas: Se utiliza Bcrypt con 10 rondas de salting. Ninguna contrasena se guarda en texto plano ni se expone en las respuestas JSON.
- Autenticacion sin Estado (Stateless): Los tokens JWT contienen firma HMAC-SHA256 y expiran en 8 horas por defecto.
- Cabeceras HTTP Defensivas: Helmet elimina cabeceras como X-Powered-By y aplica politicas restrictivas contra ataques XSS y Clickjacking.
- Control CORS Estricto: Solo las URLs definidas en CORS_ORIGIN tienen permitido comunicarse con la API desde el navegador.
La persistencia de Nicabliss API esta respaldada por Turso Web, un motor de base de datos relacional distribuido en el Edge basado en LibSQL (fork moderno y optimizado de SQLite).
erDiagram
USERS {
TEXT id PK "Identificador único (usr_admin_001 o UUID)"
TEXT username UK "Nombre de usuario único para login"
TEXT email UK "Correo electrónico corporativo único"
TEXT password_hash "Hash bcrypt (10 salt rounds)"
TEXT role "Rol RBAC: ADMIN, RECEPTIONIST, STAFF"
TEXT full_name "Nombre completo del usuario"
TEXT created_at "Timestamp ISO 8601 UTC"
}
GUESTS {
INTEGER id PK "Autoincremental"
TEXT nombre "Nombre completo del huésped titular"
TEXT documento "Cédula o pasaporte"
TEXT habitacion "Habitación asignada (ej. Habitación 01)"
TEXT entrada "Fecha check-in (YYYY-MM-DD)"
TEXT salida "Fecha check-out (YYYY-MM-DD)"
TEXT estado "Estado: Activo, Finalizado, Reservado"
TEXT created_at "Timestamp de creación"
}
BILLING_ACCOUNTS {
INTEGER id PK "Identificador numérico de cuenta"
INTEGER guest_id FK "Vínculo suave opcional (SET NULL)"
TEXT huesped "Snapshot inmutable del huésped"
TEXT habitacion "Snapshot de habitación asignada"
TEXT concepto "Concepto de cargo (Hospedaje, etc.)"
REAL total "Importe total (> 0)"
REAL pagado "Monto abonado (>= 0)"
REAL saldo "Saldo pendiente (total - pagado)"
TEXT estado "Estado: Pendiente, Parcial, Pagado"
TEXT fecha "Fecha de facturación (YYYY-MM-DD)"
}
FOOD_ORDERS {
INTEGER id PK "Identificador numérico de comanda"
TEXT order_code UK "Código amigable único (#PED-xxx)"
INTEGER guest_id FK "Vínculo suave opcional (SET NULL)"
TEXT huesped "Nombre del comensal o huésped"
TEXT habitacion "Habitación o destino de entrega"
TEXT productos "Detalle de platillos y bebidas"
REAL total "Importe total de comanda"
TEXT estado "Pendiente, En preparación, En camino, Entregado, Cancelado"
TEXT fecha "Fecha de la orden"
}
LAUNDRY_ORDERS {
INTEGER id PK "Identificador numérico de orden"
INTEGER guest_id FK "Vínculo suave opcional (SET NULL)"
TEXT huesped "Nombre del huésped solicitante"
TEXT habitacion "Habitación de entrega"
TEXT prendas "Array JSON con desglose de prendas"
INTEGER total_prendas "Conteo de prendas (> 0)"
REAL total "Costo total a $0.50 por prenda"
TEXT estado "Pendiente, En proceso, Listo, Entregado, Cancelado"
TEXT fecha "Fecha de recepción"
TEXT observaciones "Instrucciones de planchado/cuidado"
}
CASH_SESSIONS {
INTEGER id PK "Identificador de turno de caja"
TEXT responsable "Usuario a cargo del turno"
TEXT apertura "Fecha y hora de inicio"
TEXT cierre "Fecha y hora de cierre (NULL si abierto)"
REAL fondo_inicial "Fondo base en efectivo (>= 0)"
REAL ingresos_efectivo "Total cobrado en efectivo"
REAL ingresos_digitales "Total cobrado en tarjeta/transferencia"
REAL salidas_efectivo "Total de egresos/gastos en efectivo"
REAL efectivo_esperado "Balance teórico calculado"
REAL efectivo_contado "Efectivo físico contado en arqueo"
REAL diferencia "Descuadre (efectivoContado - efectivoEsperado)"
TEXT observaciones "Notas del cierre"
INTEGER is_closed "0: Turno Activo | 1: Turno Cerrado"
}
CASH_MOVEMENTS {
INTEGER id PK "Identificador de movimiento"
INTEGER session_id FK "Turno asociado (CASCADE)"
TEXT fecha "Fecha y hora del movimiento"
TEXT tipo "Ingreso o Salida"
TEXT concepto "Hospedaje, Alimentos, Lavandería, Gasto, etc."
TEXT descripcion "Detalle del movimiento"
TEXT metodo "Efectivo, Transferencia o Tarjeta"
REAL monto "Importe del movimiento (> 0)"
}
CASH_SESSIONS ||--|{ CASH_MOVEMENTS : "1:N Estricta (ON DELETE CASCADE)"
GUESTS ||--o{ BILLING_ACCOUNTS : "1:N Híbrida (SET NULL + Snapshot)"
GUESTS ||--o{ FOOD_ORDERS : "1:N Híbrida (SET NULL + Snapshot)"
GUESTS ||--o{ LAUNDRY_ORDERS : "1:N Híbrida (SET NULL + Snapshot)"
- Conexion Segura LibSQL:
@libsql/clientgestiona peticiones HTTP/WebSocket seguras hacia el cluster de Turso (libsql://...), ofreciendo tiempos de respuesta en microsegundos sin requerir compiladores C++ nativos. - Relaciones Fuertes (CASCADE): Cada registro en
cash_movementspertenece estrictamente a una sesion decash_sessions. - Patron Snapshot Contable (Inmutabilidad): Las cuentas de cobro, comandas y lavanderia conservan
huespedyhabitacioncomo copia fija, de forma que el historial fiscal permanece inalterable aunque un huesped finalice su estancia (ON DELETE SET NULL). - Indice Unico Parcial Anticoncurrencia:
Garantiza a nivel de motor de base de datos que sea imposible tener dos turnos de caja abiertos simultaneamente, blindando el sistema contra condiciones de carrera.
CREATE UNIQUE INDEX idx_unique_active_cash_session ON cash_sessions(is_closed) WHERE is_closed = 0;
| Comando NPM | Accion |
|---|---|
npm run db:migrate |
Ejecuta el esquema DDL relacional (src/db/schema.sql) en Turso. |
npm run db:seed |
Puebla los datos iniciales necesarios si las tablas estan vacias. |
npm start / npm run dev |
Inicializa automaticamente las migraciones y seeds durante el bootstrap del servidor. |
La API cuenta con soporte completo y optimizado para ejecutarse en la infraestructura Serverless de Vercel.
vercel.json: Regla de reescritura que redirige todo el trafico/(.*)hacia la funcion serverless/api/index.api/index.ts: Punto de entrada Serverless que exporta la aplicacion Express configurada..vercelignore: Exclusiones para aligerar el empaquetado (omite bases de datos locales, pruebas y dependencias superfluas).
En el panel de administracion de Vercel (Project Settings > Environment Variables), configure las siguientes variables de produccion:
| Variable | Descripcion | Valor de Ejemplo |
|---|---|---|
NODE_ENV |
Modo de entorno | production |
JWT_SECRET |
Clave secreta para firma de tokens Bearer | clave_secreta_alta_entropia |
JWT_EXPIRES_IN |
Caducidad de la sesion | 8h |
CORS_ORIGIN |
Origenes permitidos del frontend (separados por coma) | https://tu-frontend.vercel.app |
TURSO_DATABASE_URL |
URL de la base de datos Turso | libsql://tu-base-datos.turso.io |
TURSO_AUTH_TOKEN |
Token de autenticacion de Turso | eyJhbGciOi... |
Dado que el entorno de ejecucion Serverless es efimero y con sistema de archivos de solo lectura, la creacion de tablas (DDL) y la carga de datos iniciales se realizan desde su maquina local contra la base de datos de Turso antes de realizar el despliegue:
# Ejecutar migraciones DDL contra Turso
npm run db:migrate
# Cargar datos iniciales
npm run db:seed- Confirme y suba sus cambios a la rama principal en GitHub.
- En la consola de Vercel, importe el repositorio
nicabliss_api. - Configure las variables de entorno detalladas en la seccion anterior.
- Haga clic en Deploy.
# Autenticarse en Vercel
npx vercel login
# Despliegue de prueba (Preview)
npx vercel
# Despliegue a produccion
npx vercel --prod