Skip to content

Ejercicios

Endpoints para la biblioteca de ejercicios.

El siguiente modelo de Prisma pertenece al schema fitness:

model Exercise {
id String @id @default(cuid())
name String
gifUrl String? @map("gif_url")
targetMuscles String[] @map("target_muscles")
secondaryMuscles String[] @map("secondary_muscles")
bodyParts String[] @map("body_parts")
equipments String[]
instructions String[]
workoutExercises WorkoutExercise[]
routineExercises RoutineExercise[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("exercises")
@@schema("fitness")
}

Obtener una lista de ejercicios con filtros.

  • URL: /api/v1/exercises
  • Método: GET
  • Autenticación Requerida:

Este endpoint obtiene ejercicios de la biblioteca con caching y filtrado:

  1. Sistema de Caché (Redis):

    • Clave: exercises:list:{filtros_serializados}
    • TTL: 5 minutos para listas
    • Si existe en caché, retorna inmediatamente
  2. Filtros disponibles:

    • name: Búsqueda por nombre (contains, case-insensitive)
    • targetMuscles: Filtra por músculos objetivo (hasSome para arrays)
    • secondaryMuscles: Filtra por músculos secundarios
    • bodyParts: Filtra por partes del cuerpo
    • equipments: Filtra por equipamiento necesario
  3. Paginación: Usa page y limit con cálculo de skip

  4. Ordenamiento: Por nombre ascendente

  5. Transacción: Ejecuta findMany y count en paralelo

  • name: Buscar por nombre
  • targetMuscles: Filtrar por músculo(s) objetivo
  • secondaryMuscles: Filtrar por músculo(s) secundario(s)
  • bodyParts: Filtrar por parte(s) del cuerpo
  • equipments: Filtrar por equipamiento(s)
  • page: Número de página (por defecto: 1)
  • limit: Resultados por página (por defecto: 10)
{
"data": [
{
"id": "...",
"name": "Squat",
"targetMuscles": ["Quadriceps"],
"secondaryMuscles": ["Glutes", "Hamstrings"],
"instructions": "...",
"gifUrl": "..."
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 150,
"totalPages": 15
}
}
import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.exercises.$get({
query: {
targetMuscles: 'Legs'
}
})

Obtener detalles de un ejercicio específico.

  • URL: /api/v1/exercises/:id
  • Método: GET
  • Autenticación Requerida:

Este endpoint obtiene un ejercicio específico con caché:

  1. Verifica caché: Clave exercises:{id}, TTL 24 horas
  2. Si no está en caché: Busca en BD con findUniqueOrThrow
  3. Guarda en caché el resultado para futuras consultas
  4. Retorna todos los campos del ejercicio
{
"data": {
"id": "...",
"name": "Squat",
"description": "...",
"targetMuscles": ["Quadriceps"],
"secondaryMuscles": ["Glutes"],
"bodyParts": ["Legs"],
"equipments": ["Barbell"],
"instructions": "...",
"gifUrl": "..."
}
}
import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.exercises[':id'].$get({
param: { id: 'exercise_id' }
})

Añadir un nuevo ejercicio a la biblioteca.

  • URL: /api/v1/exercises
  • Método: POST
  • Autenticación Requerida:

Este endpoint crea un nuevo ejercicio:

  1. Crea el ejercicio en la base de datos con todos los campos proporcionados
  2. Invalida caché de listas: Elimina todas las claves exercises:list:* para que las búsquedas reflejen el nuevo ejercicio
  3. Retorna el ejercicio creado
  • name: Nombre del ejercicio (requerido)
  • description: Descripción detallada
  • targetMuscles: Array de músculos principales
  • secondaryMuscles: Array de músculos secundarios
  • bodyParts: Partes del cuerpo trabajadas
  • equipments: Equipamiento necesario
  • instructions: Instrucciones paso a paso
  • gifUrl: URL del GIF demostrativo
{
"name": "Squat",
"description": "Lower body exercise",
"targetMuscles": ["Quadriceps"],
"secondaryMuscles": ["Glutes", "Hamstrings"],
"bodyParts": ["Legs"],
"equipments": ["Barbell"],
"instructions": "1. Stand with feet shoulder-width apart...",
"gifUrl": "https://..."
}
import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.exercises.$post({
json: {
name: 'Squat',
description: 'Lower body exercise',
targetMuscles: ['Quadriceps'],
secondaryMuscles: ['Glutes'],
bodyParts: ['Legs'],
equipments: ['Barbell']
}
})

Actualizar un ejercicio existente.

  • URL: /api/v1/exercises/:id
  • Método: PUT
  • Autenticación Requerida:

Este endpoint actualiza un ejercicio existente:

  1. Actualiza el ejercicio con los campos proporcionados
  2. Invalida caché individual: Elimina exercises:{id}
  3. Invalida caché de listas: Elimina exercises:list:*
  4. Retorna el ejercicio actualizado
{
"name": "Barbell Squat",
"description": "Updated description"
}
import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.exercises[':id'].$put({
param: { id: 'exercise_id' },
json: {
name: 'Barbell Squat'
}
})

Eliminar un ejercicio.

  • URL: /api/v1/exercises/:id
  • Método: DELETE
  • Autenticación Requerida:

Este endpoint elimina un ejercicio:

  1. Invalida caché individual: Elimina exercises:{id}
  2. Invalida caché de listas: Elimina exercises:list:*
  3. Elimina el ejercicio de la base de datos
  4. Retorna el ejercicio eliminado

Advertencia: Verificar que el ejercicio no esté siendo usado en rutinas activas antes de eliminar.

import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.exercises[':id'].$delete({
param: { id: 'exercise_id' }
})