Arquitectura End-to-End

Servicio de Imágenes

Documentación del sistema de procesamiento, subida y almacenamiento de imágenes. Gestión local en disco con optimización en cliente.

Shipped
3
API Endpoints
12
Storage Folders
4
Presets de Optimización

Visión General (Arquitectura)

El sistema de imágenes actual prescinde de procesamiento en el servidor (sin sharp o imagemagick) en favor de la optimización en el navegador del cliente mediante la API de Canvas. El backend funciona como un almacén de archivos estático.

1. Frontend
@pamaconu/core
ImageOptimizationService comprime en Canvas y genera WebP.
2. Backend
@happnest/backend
Multer valida (10MB max). LocalUploadController sanitiza y guarda.
3. Local Disk
/uploads/{public|private}/{folder}/{id}
Archivos servidos vía express.static o ruta auth.

API Endpoints (Backend)

Rutas definidas en local-upload.routes.ts, expuestas en /api/v1/local-storage.

Method / Path Auth Descripción
POST /upload Sube un archivo (multipart/form-data). Requiere folder, entityId, y file. Retorna URL pública o privada según la carpeta.
GET /private/* Sirve imágenes de carpetas privadas verificando la cookie de sesión del usuario.
POST /delete Elimina un archivo del disco. Requiere el filePath exacto.

Storage Folders

Definidas en config/storage-folders.ts. Determinan si la imagen se sirve libremente o requiere autenticación.

Public experiences Imágenes de experiencias
Public webchecking Recursos webcheckin
Public themes / branding Assets de marca
Public gallery / logos / hotels General
Private users / avatars Perfiles de usuario
Private tasks / checkin Info de personal/huésped
Private companies Doc interna de empresa

Optimización en Cliente

Para aligerar el servidor, la compresión sucede en el navegador usando ImageOptimizationService (core). Convierte a WebP y reduce dimensiones.

thumbnail

200×200 px
Quality: 70%
WebP

preview

400×400 px
Quality: 80%
WebP

gallery

800×600 px
Quality: 85%
WebP

fullsize

1920×1080 px
Quality: 90%
WebP

Variant Generation (Admin/Enterprise)

El método uploadWithVariants (en AdminStorageService) automatiza la creación y subida en paralelo de todas las variantes de una misma imagen. Nomenclatura generada:

// Base name + timestamp + random + variant
{prefix}_mi_imagen_1684300000_a1b2c3_thumb.webp
{prefix}_mi_imagen_1684300000_a1b2c3_preview.webp
{prefix}_mi_imagen_1684300000_a1b2c3_gallery.webp
{prefix}_mi_imagen_1684300000_a1b2c3_full.webp
    

Integración UI: OptimizedImage

El componente React OptimizedImage (en @pamaconu/core) es la forma estándar de mostrar imágenes.

01 Características clave
  • Lazy Loading: Usa IntersectionObserver para cargar solo cuando es visible.
  • Blur Placeholder: Muestra un fondo o esqueleto antes de que cargue la imagen real.
  • Caché LRU: Caché en memoria de hasta 100 entradas con 24h TTL para evitar refetching en renders.
  • Fallback: Si falla, muestra un SVG o placeholder por defecto.
02 Ejemplo de uso
import { OptimizedImage } from "@pamaconu/core";

function Avatar() {
  return (
    <OptimizedImage
      src="api/v1/local-storage/private/avatars/123/img_thumb.webp"
      alt="User avatar"
      className="w-10 h-10 rounded-full"
      variant="thumbnail"
    />
  );
}
        

Seguridad

Uploads

File type whitelist (jpeg, png, webp, gif, svg+xml). Límite duro de Multer: 10 MB. El entityId se sanitiza contra Path Traversal (.., /, \0).

Downloads (Private)

El endpoint /private/* comprueba la cookie JWT. Antes de servir con res.sendFile, verifica que el path resultante esté estrictamente dentro del directorio /private/ para evitar escapes.