Desarrollo web

El migrador ya habla con el WordPress de producción

Primer piloto contra el WordPress real: autenticación dual, prefijos de tablas, catálogos de comarcas y HTML de Gutenberg convertido a Lexical.

El migrador ya habla con el WordPress de producción

Llevo tres semanas con el migrador trabajando sobre datos de prueba. Hoy lo he puesto delante del WordPress real: la base de datos de producción, con sus prefijos rarísimos y las taxonomías de Toolset. La fase 3 ya no es un borrador: el piloto importa.

Dos puertas para entrar en Payload

El primer problema ni siquiera era de migración: era de autenticación. El plugin de API keys de Payload pide configuración manual desde la interfaz, y yo quería un camino que funcionara siempre. Solución: modo doble. Si hay PAYLOAD_API_KEY, se usa API key; si no, login con email y contraseña (JWT), que funciona out-of-the-box. Y si no hay nada de nada, el script se para con un RuntimeError que lo explica.

Encontrar las tablas buenas

Para detectar el prefijo de las tablas WordPress hacía un LIKE '%\_posts'. PyMySQL se lo come como un especificador de formato, y además el primer candidato que salía era una tabla de Mailpoet, no del core. Dos correcciones: escapar el porcentaje (%%) y cruzar con las tablas *_options, que son las que delatan el core de WordPress. Si hay varias candidatas, gana el prefijo más corto.

Comarcas, municipios y detalles que no perdonan

En el primer pilot nada enlazaba: las comarcas no se resolvían a IDs, el seed decía berguedà con acento y el WordPress lo tiene sin él, y Payload quería enteros donde le pasaba strings. Ahora los catálogos de comarcas y municipios se crean solos (idempotentes) y las relaciones van con el tipo correcto. Para Bagà han salido 13 posts: 1 de cultura y 12 eventos del calendario.

De HTML de Gutenberg a Lexical

El contenido del WP llegaba con comentarios <!-- wp:paragraph --> que Payload escapaba y mostraba literalmente en la página. He reescrito el conversor con html.parser: limpia los comentarios de Gutenberg, mapea párrafos, encabezados y listas, y conserva negritas y cursivas dentro del texto. Los enlaces, además, pedían campos extra en el nodo (id, direction, format): sin ellos, el admin petaba con un React error #418 y escondía todos los campos richText. Con el parser nuevo, las dos piezas del último piloto se ven limpias en el frontend.

De paso: dependencias al día

He aprovechado para poner Payload 3.89, Next 15.4.11 y React 19.0.1: el peer dep de Payload lo exigía. El error #418 ha sobrevivido a la actualización, que era otra pista de que era estructural y no de versión.

Balance del día: 29 smoke tests en verde, dos pilotos importados con portada y meta descripción, y la sensación de que la fase 3 por fin camina sola.