From a5ede05d96da117734a5aee0233ac1b55e645ff6 Mon Sep 17 00:00:00 2001 From: Cristian Felipe Cruz Buitron Date: Sun, 6 Sep 2026 03:43:47 +0000 Subject: [PATCH] fix(product-import): generar handle ASCII-safe en vez del default de Medusa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3 productos importados con título acentuado (ñ/tildes) quedaron con handle no-ASCII y daban 404 real al entrar por shop.cruzcloud.net -- el tunel/ ingress público rompe rutas con UTF-8 no-ASCII en el path, confirmado en vivo comparando el mismo request directo al servicio (200 OK) contra el dominio público (404). Se genera el handle explícito (slugify propio, sin dependencia nueva) con sufijo único por fila para evitar colisiones entre títulos parecidos. Los 3 productos ya publicados con handle roto se corrigieron en caliente vía Admin API, sin esperar este deploy. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01SEsGCsCmxkyXi9XctNdrT1 --- .../src/api/admin/product-import/route.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/workloads/commerce-backend/src/api/admin/product-import/route.ts b/workloads/commerce-backend/src/api/admin/product-import/route.ts index 64c54f6..b64d39e 100644 --- a/workloads/commerce-backend/src/api/admin/product-import/route.ts +++ b/workloads/commerce-backend/src/api/admin/product-import/route.ts @@ -53,6 +53,28 @@ type RowResult = { error?: string; }; +// Medusa genera el handle por defecto solo en minusculas + espacios a +// guiones, sin quitar tildes/enies -- confirmado en vivo: 3 productos +// importados con titulo acentuado (ej. "niñas", "Lógicos") quedaron con +// handle como "...niñas..." y daban 404 real al entrar por +// shop.cruzcloud.net (el tunel/ingress publico rompe rutas con UTF-8 +// no-ASCII en el path, aunque el mismo request funciona perfecto pegandole +// directo al servicio dentro del cluster). Se genera el handle nosotros +// mismos, ASCII-only, en vez de dejarselo al default de Medusa. El sufijo +// corto evita colisiones entre titulos parecidos/repetidos sin necesidad +// de revisar unicidad antes de crear. +function slugify(title: string, uniquePart: string): string { + const base = title + .normalize("NFD") + .replace(/[̀-ͯ]/g, "") + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, "") + .slice(0, 80) + .replace(/-+$/g, ""); + return `${base || "producto"}-${uniquePart}`; +} + function extensionFromContentType(contentType: string | null, url: string): string { if (contentType?.includes("png")) return "png"; if (contentType?.includes("webp")) return "webp"; @@ -201,6 +223,7 @@ export async function POST(req: MedusaRequest<{ csv: string }>, res: MedusaRespo products: [ { title, + handle: slugify(title, `${Date.now().toString(36)}${index}`), description: row.descripcion || undefined, status: "published", thumbnail: uploadedFiles[0]?.url,