Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/midudev/jscamp/llms.txt

Use this file to discover all available pages before exploring further.

La API DevJobs es una API REST construida con Express v5 en el módulo 04 y posteriormente respaldada por SQLite con TypeScript en el módulo 08. Todos los endpoints operan sobre listados de ofertas de empleo (jobs) y siguen las convenciones REST estándar. La validación de datos se realiza con Zod en ambas versiones.

Base URL

http://localhost:3000
Todas las rutas de jobs están disponibles bajo el prefijo /jobs.

Endpoints

GET /jobs

Devuelve el listado completo de ofertas de empleo. Admite parámetros de consulta opcionales para filtrar y paginar resultados. Parámetros de query
text
string
Filtra las ofertas cuyo titulo o descripcion contengan el texto indicado (búsqueda sin distinción de mayúsculas/minúsculas).
technology
string
Filtra las ofertas por tecnología (p. ej. react, node, typescript).
title
string
Filtra las ofertas por título del puesto.
level
string
Filtra las ofertas por nivel de experiencia (p. ej. junior, mid-level, senior).
limit
number
Número máximo de resultados a devolver. Por defecto: 10.
offset
number
Número de resultados a saltar (para paginación). Por defecto: 0.
Ejemplo de respuesta
{
  "data": [
    {
      "id": "7a4d1d8b-1e45-4d8c-9f1a-8c2f9a9121a4",
      "titulo": "Desarrollador de Software Senior",
      "empresa": "Tech Solutions Inc.",
      "ubicacion": "Remoto",
      "descripcion": "Buscamos un ingeniero de software con experiencia en desarrollo web y conocimientos en JavaScript, React y Node.js. El candidato ideal debe ser capaz de trabajar en equipo y tener buenas habilidades de comunicación.",
      "data": {
        "technology": ["react", "node", "javascript"],
        "modalidad": "remoto",
        "nivel": "senior"
      }
    },
    {
      "id": "d35b2c89-5d60-4f26-b19a-6cfb2f1a0f57",
      "titulo": "Analista de Datos",
      "empresa": "Data Driven Co.",
      "ubicacion": "Ciudad de México",
      "descripcion": "Estamos buscando un analista de datos con experiencia en el manejo de grandes conjuntos de datos y herramientas de visualización. Se requiere conocimiento en SQL, Python y R.",
      "data": {
        "technology": ["python", "sql", "r", "pandas"],
        "modalidad": "cdmx",
        "nivel": "junior"
      }
    }
  ],
  "total": 2,
  "limit": 10,
  "offset": 0
}
Campos de la respuesta
data
object[]
Array con las ofertas de empleo que coinciden con los filtros aplicados.
total
number
Número total de ofertas que coinciden con los filtros (antes de aplicar paginación).
limit
number
Número máximo de resultados devueltos (el valor del parámetro limit usado).
offset
number
Número de resultados omitidos (el valor del parámetro offset usado).

GET /jobs/:id

Devuelve una única oferta de empleo identificada por su id. Parámetros de ruta
id
string
required
Identificador único (UUID) de la oferta de empleo.
Respuestas
{
  "id": "7a4d1d8b-1e45-4d8c-9f1a-8c2f9a9121a4",
  "titulo": "Desarrollador de Software Senior",
  "empresa": "Tech Solutions Inc.",
  "ubicacion": "Remoto",
  "descripcion": "Buscamos un ingeniero de software con experiencia...",
  "data": {
    "technology": ["react", "node", "javascript"],
    "modalidad": "remoto",
    "nivel": "senior"
  },
  "content": {
    "description": "Tech Solutions Inc. está buscando un Ingeniero de Software Senior...",
    "responsibilities": "- Diseñar, desarrollar y mantener aplicaciones web...",
    "requirements": "- Licenciatura en Informática o campo relacionado...",
    "about": "Tech Solutions Inc. es una empresa de tecnología innovadora..."
  }
}

POST /jobs

Crea una nueva oferta de empleo. El cuerpo de la petición se valida con Zod antes de ser procesado. Parámetros del body
titulo
string
required
Título del puesto. Mínimo 3 caracteres, máximo 100.
empresa
string
required
Nombre de la empresa que publica la oferta.
ubicacion
string
required
Ubicación del puesto de trabajo.
descripcion
string
Descripción detallada del puesto (opcional).
data
object
required
Objeto con metadatos adicionales de la oferta.
Ejemplo de request
curl -X POST http://localhost:3000/jobs \
  -H "Content-Type: application/json" \
  -d '{
    "titulo": "Frontend Developer",
    "empresa": "Bright Web Studio",
    "ubicacion": "Valencia",
    "descripcion": "Buscamos un desarrollador frontend con React y TypeScript.",
    "data": {
      "technology": ["react", "typescript", "tailwind"],
      "modalidad": "hibrido",
      "nivel": "mid-level"
    }
  }'
Respuesta exitosa (201 Created)
{
  "id": "f3a8c2d1-9b4e-4f7a-a1c3-8e5d2f6b9a0c",
  "titulo": "Frontend Developer",
  "empresa": "Bright Web Studio",
  "ubicacion": "Valencia",
  "data": {
    "technology": ["react", "typescript", "tailwind"],
    "modalidad": "hibrido",
    "nivel": "mid-level"
  }
}
Respuesta de error (400 Bad Request)
{
  "error": "Invalid request",
  "details": [
    {
      "code": "too_small",
      "minimum": 3,
      "message": "El título debe tener al menos 3 caracteres",
      "path": ["titulo"]
    }
  ]
}

PATCH /jobs/:id

Actualiza parcialmente una oferta de empleo existente. Todos los campos del body son opcionales: solo se modificarán los campos que se envíen. Parámetros de ruta
id
string
required
Identificador único (UUID) de la oferta a actualizar.
Parámetros del body (todos opcionales)
titulo
string
Nuevo título del puesto. Mínimo 3 caracteres, máximo 100.
empresa
string
Nuevo nombre de la empresa.
ubicacion
string
Nueva ubicación del puesto.
descripcion
string
Nueva descripción del puesto.
data
object
Objeto parcial con metadatos: technology, modalidad, nivel.
Ejemplo de request
curl -X PATCH http://localhost:3000/jobs/7a4d1d8b-1e45-4d8c-9f1a-8c2f9a9121a4 \
  -H "Content-Type: application/json" \
  -d '{
    "ubicacion": "Madrid",
    "data": {
      "modalidad": "hibrido",
      "nivel": "senior",
      "technology": ["react", "node", "typescript"]
    }
  }'
Devuelve el objeto del job actualizado.

PUT /jobs/:id

Reemplaza completamente una oferta de empleo existente. A diferencia de PATCH, este método sustituye el objeto entero por los datos enviados en el body. Parámetros de ruta
id
string
required
Identificador único (UUID) de la oferta a reemplazar.
Parámetros del body El body debe contener todos los campos obligatorios del recurso, ya que se realiza un reemplazo completo (mismos campos requeridos que POST /jobs).
Devuelve el objeto del job reemplazado.

DELETE /jobs/:id

Elimina permanentemente una oferta de empleo por su id. Parámetros de ruta
id
string
required
Identificador único (UUID) de la oferta a eliminar.
Ejemplo de request
curl -X DELETE http://localhost:3000/jobs/7a4d1d8b-1e45-4d8c-9f1a-8c2f9a9121a4
La oferta fue eliminada correctamente. El body de la respuesta está vacío.

Esquema Zod de Validación

Módulo 04 — Express (JavaScript)

El esquema de validación usado en 04-express/schemas/jobs.js:
import * as z from 'zod'

const jobSchema = z.object({
  titulo: z
    .string({ error: 'El título es obligatorio' })
    .min(3, 'El título debe tener al menos 3 caracteres')
    .max(100, 'El título no puede exceder los 100 caracteres'),
  empresa: z.string(),
  ubicacion: z.string(),
  descripcion: z.string().optional(),
  data: z.object({
    technology: z.array(z.string()),
    modalidad: z.string(),
    nivel: z.string(),
  }),
})

export function validateJob(input) {
  return jobSchema.safeParse(input)
}

export function validatePartialJob(input) {
  return jobSchema.partial().safeParse(input)
}

Módulo 08 — SQLite + TypeScript

El esquema tipado de 08-sql/backend/src/schemas/job.ts añade validaciones de enum y tipos inferidos automáticamente:
import { z } from 'zod'

export const jobDataSchema = z.object({
  technology: z.array(z.string()),
  modality: z.enum(['remote', 'onsite', 'hybrid']),
  level: z.enum(['junior', 'mid', 'senior'])
})

export const jobContentSchema = z.object({
  description: z.string(),
  responsibilities: z.string(),
  requirements: z.string(),
  about: z.string()
})

export const jobSchema = z.object({
  title: z.string({
    required_error: 'Title is required',
    invalid_type_error: 'Title must be a string'
  }).min(3, 'Title must be at least 3 characters'),
  company: z.string({ required_error: 'Company is required' }),
  location: z.string({ required_error: 'Location is required' }),
  description: z.string({ required_error: 'Description is required' }),
  data: jobDataSchema,
  content: jobContentSchema.optional()
})

// Tipos inferidos automáticamente desde Zod
export type JobInput = z.infer<typeof jobSchema>
export type JobDataInput = z.infer<typeof jobDataSchema>
export type JobContentInput = z.infer<typeof jobContentSchema>

// Función de validación
export function validateJob(input: unknown) {
  return jobSchema.safeParse(input)
}

export function validatePartialJob(input: unknown) {
  return jobSchema.partial().safeParse(input)
}
En el módulo 08, la misma API está respaldada por SQLite en lugar del array JSON en memoria. Los datos persisten entre reinicios del servidor y el esquema Zod añade validaciones de enum estrictas para modality ("remote" | "onsite" | "hybrid") y level ("junior" | "mid" | "senior"). Los nombres de campo cambian ligeramente: titulotitle, empresacompany, ubicacionlocation.

Resumen de Endpoints

MétodoRutaDescripciónCódigo éxito
GET/jobsLista todas las ofertas200
GET/jobs/:idObtiene una oferta por ID200
POST/jobsCrea una nueva oferta201
PATCH/jobs/:idActualiza parcialmente una oferta200
PUT/jobs/:idReemplaza completamente una oferta200
DELETE/jobs/:idElimina una oferta204

Build docs developers (and LLMs) love