CreaRack-SL

Endpoint: Quick Links API (Cloudflare Workers)

Endpoint: Quick Links API (Cloudflare Workers)

API REST implementada como Cloudflare Pages Functions que gestiona los Quick Links del workspace CreaRack — accesos directos a URLs internas y externas categorizados y posicionables.

Archivos fuente

ArchivoResponsabilidad
functions/api/quicklinks/index.tsColección: GET /api/quicklinks, POST /api/quicklinks
functions/api/quicklinks/[id].tsRecurso individual: GET, PUT, DELETE /api/quicklinks/:id

Esquema de la tabla D1

CREATE TABLE quick_links (
  id          INTEGER PRIMARY KEY AUTOINCREMENT,
  label       TEXT NOT NULL,           -- máx 80 chars
  url         TEXT NOT NULL,           -- máx 500 chars
  description TEXT,
  category    TEXT DEFAULT 'general',  -- ver VALID_CATEGORIES
  icon_url    TEXT,
  position    INTEGER DEFAULT 0,
  owner_id    TEXT,
  created_at  TEXT DEFAULT (datetime('now')),
  updated_at  TEXT DEFAULT (datetime('now'))
);

-- Desde migración 0025 (2026-05-14):
CREATE UNIQUE INDEX idx_quick_links_label_url_unique ON quick_links(label, url);

Categorías válidas (VALID_CATEGORIES)

general, monitoring, admin, tools, docs, external (y posiblemente otras definidas en el handler). Cualquier valor no reconocido se normaliza a general.


Endpoints

Lista Quick Links. Soporta filtrado opcional por query param category.

Respuesta: 200 OK → array de objetos quick_link.


POST /api/quicklinks

Crea un Quick Link nuevo.

Body JSON:

{
  "label": "string (requerido, máx 80)",
  "url":   "string (requerido, máx 500)",
  "description": "string (opcional)",
  "category":    "string (opcional, default: general)",
  "icon_url":    "string (opcional)",
  "position":    "integer (opcional)",
  "owner_id":    "string (opcional)"
}

Respuestas:

StatusCondición
201 CreatedQuick Link creado correctamente
400 Bad Requestlabel o url ausentes, o superan límite de longitud
409 ConflictYa existe un Quick Link con ese mismo (label, url)

Implementación post-fix (migración 0025):

INSERT INTO quick_links (label, url, ...)
VALUES (?, ?, ...)
ON CONFLICT(label, url) DO NOTHING
RETURNING *

Si RETURNING * devuelve null (conflict ignorado), el handler responde 409 con { error: 'Ya existe un Quick Link con ese nombre y URL' }.


GET /api/quicklinks/:id

Devuelve un Quick Link por ID.

Respuestas: 200 OK / 404 Not Found.


PUT /api/quicklinks/:id

Actualiza campos de un Quick Link. Acepta cualquier subconjunto de los campos editables (label, url, description, category, icon_url, position). Actualiza updated_at automáticamente.

Respuestas:

StatusCondición
200 OKActualización correcta
404 Not FoundID no existe
409 ConflictEl nuevo (label, url) colisiona con otro Quick Link existente

Implementación post-fix: el UPDATE se envuelve en try/catch; si el error incluye 'UNIQUE constraint failed' → 409.


DELETE /api/quicklinks/:id

Elimina un Quick Link por ID.

Respuestas: 200 OK / 404 Not Found.


Logging de actividad

Todos los endpoints de escritura (POST, PUT, DELETE) llaman a logActivity(env, { actor, action, ... }) extrayendo el actor desde la cabecera de request. El actor se resuelve con la función helper actorFrom(request).


Notas de fiabilidad

  • UNIQUE INDEX en (label, url) — introducido en migración 0025 (2026-05-14) tras el incidente de duplicación por re-aplicación de seeds. Garantiza idempotencia a nivel BD.
  • ON CONFLICT DO NOTHING en POST — protege contra dobles submit en el modal de la UI y contra re-seeds accidentales.
  • try/catch en PUT — captura violaciones de UNIQUE al editar, evitando errores 500 no controlados.

Véase también

  • [[incident—20260514—quicklinks-duplicados-d1-migrations]]
  • [[workspace—que-es-workspace]]
  • [[workspace—agentes-ia]]