rp-source-wordpress
Adaptateur source WordPress / WooCommerce source adapter. Encapsule tous les détails spécifiques à WordPress que les compétences agnostiques vis-à-vis de la plateforme ne doivent pas coder en dur : comment capturer le schéma, comment lire les données, les modèles d'authentification, la pagination et les particularités REST.
Quand cette compétence est utilisée
Ce n'est pas une étape du flux de migration — c'est une référence consultée par deux étapes :
rp-discoveryconsulte la section Capture pour échantillonner la source et produire les artefacts canoniquessource-profile.md+source-schema.json.rp-import-codegenconsulte la section Read contract pour générer un lecteur qui extrait en masse les données WordPress correctement (authentification, pagination,wc/v3vswp/v2) dans des fichiers durables locaux au projet pour l'étape d'import ultérieure.
rp-execute-import ne consulte jamais cette compétence — au moment où l'exécution s'exécute,
la connaissance spécifique à WordPress est déjà intégrée dans le code du lecteur généré.
Garder la connaissance WordPress ici est ce qui permet au reste du flux de rester agnostique
vis-à-vis de la plateforme.
Identité de plateforme
- Plateforme source : WordPress (REST core
wp/v2), optionnellement WooCommerce (wc/v3). - Détectez en frappant
<base-url>/wp-json/— l'index REST liste les espaces de noms annoncés. - Définissez
"platform": "wordpress"(et notez la présence de WooCommerce danssourceMeta) dans lesource-schema.jsonémis.
Capture (discovery-time)
Échantillonnage de la source pour apprendre sa forme — pas une export en masse.
Avant la capture, vérifiez migrations/<project>/config/source.wordpress.env. Créez-le s'il
manque, en utilisant des valeurs vides à remplir par l'utilisateur :
WP_BASE_URL=
WP_USERNAME=
WP_APPLICATION_PASSWORD=
WP_MEDIA_URL_REWRITE_FROM=
WP_MEDIA_URL_REWRITE_TO=
WC_CONSUMER_KEY=
WC_CONSUMER_SECRET=
Requis pour une capture complète WordPress/WooCommerce :
WP_BASE_URLWP_USERNAMEWP_APPLICATION_PASSWORD
WC_CONSUMER_KEY et WC_CONSUMER_SECRET sont optionnels quand WooCommerce accepte le
Application Password WordPress pour les lectures wc/v3 ; demandez-les uniquement si les
routes WooCommerce retournent 401/403 avec le Application Password WordPress.
WP_MEDIA_URL_REWRITE_FROM et WP_MEDIA_URL_REWRITE_TO sont optionnels. Utilisez-les
quand l'API WordPress est atteinte via un tunnel public mais que les URLs de médias/fichiers
à l'intérieur des enregistrements pointent toujours vers localhost ou une autre origine
privée. S'ils sont vides, les lecteurs générés peuvent réécrire les origines localhost/privées
vers WP_BASE_URL quand WP_BASE_URL est public.
config/source.wordpress.env est un fichier porteur de secrets une fois qu'il peut contenir
des valeurs réelles. Ne le lisez pas avec des commandes qui affichent son contenu entier dans
la sortie d'outil. Vérifiez uniquement si le fichier existe et si chaque clé requise est
présente/vide/manquante ; en décrivant le statut, nommez les clés uniquement et ne renvoyez
jamais les valeurs.
-
Exécutez le script de capture déterministe depuis le répertoire de cette compétence (le dossier contenant ce
SKILL.md; voirCONVENTIONS.md) :node scripts/wp-discovery.js --base-url <url> --out-dir <migrations-root>/<project>/data/wp-discoveryIl parcourt l'index REST, exécute un
OPTIONS+ un petit échantillonGETpar entité, et écrit du markdown par entité (routes, schémas, enregistrements échantillons, comptes d'enregistrements, relations). Transmettez les options d'authentification (voir Read contract → Auth) pour une capture complète. -
Les identifiants sont requis pour une capture complète. Sans authentification, seul le contenu public publié est accessible ; les brouillons, WooCommerce (
wc/v3), les données personnelles des utilisateurs et les champs privés retournent 401/403, rendant leursrecordCount/inUsepeu fiables. Le script signale ceci dans son README sous « Incomplete Capture (Authentication) » — ne traitez pas une exécution non authentifiée comme faisant autorité. -
Distinguez les entités supportées (annoncées par l'index REST) des entités utilisées (celles avec
recordCount > 0). Les entités annoncées mais vides doivent être signalées, pas mappées comme si elles contenaient des données. -
Mappez les plugins connus aux types d'entités le cas échéant (par exemple WooCommerce → store, Seriously Simple Podcasting
ssp/v1→ podcasts, Yoast → SEO, ACF → custom fields). -
Sources localhost et URLs de médias. Une source sur
localhost,127.0.0.1ou un autre hôte privé uniquement est valide pour la découverte et les lectures de source depuis la machine de l'utilisateur. Cependant, l'import de médias Wix récupère les fichiers de l'URL à l'aide des serveurs Wix, donc les URLs de médias commehttp://localhost:8090/wp-content/uploads/...ne sont pas accessibles par Wix pendant un import en direct. Ceci est une configuration optionnelle et, autant que nous le sachions aujourd'hui, affecte seulement l'import de médias :- Préférez exposer la source locale via un tunnel HTTPS public temporaire tel que ngrok avant l'import de médias en direct.
- Ou ignorez/reportez explicitement l'import de médias et continuez avec les entités non médias.
- Si vous utilisez ngrok sur macOS :
- Installation :
brew install ngrok - Ajoutez un authtoken depuis le tableau de bord ngrok :
ngrok config add-authtoken "<YOUR_AUTHTOKEN>" - Exposez le port de la source locale, par exemple :
ngrok http 8090 - Définissez l'URL de base source sur l'URL de forwarding HTTPS :
export WP_BASE_URL=https://<id>.ngrok-free.appEnregistrez ceci danssource-profile.mdquand l'URL de source capturée est localhost, et notez si les médias utiliseront le tunnel ou seront ignorés/reportés.
- Installation :
La capture brute est une preuve, pas un artefact de transmission. rp-discovery la synthétise
dans les artefacts canoniques et enregistre les pointeurs de traçabilité (rawDiscovery,
rawFile par entité).
Read contract (codegen-time)
Ce qu'un lecteur WordPress généré doit bien faire. Capturez les faits opérationnels ci-dessous
dans source-profile.md pendant la découverte pour que codegen les ait sans les redériver.
Le lecteur généré est un extracteur, pas un chargeur en masse en mémoire. Il doit récupérer les enregistrements WordPress/WooCommerce page par page et les écrire dans des fichiers locaux au projet (par exemple des fichiers JSON paginés par entité plus un manifeste) pour que l'étape d'import puisse les lire plus tard depuis le disque sans re-récupérer la source.
Réutilisez le transport partagé — ne le régénérez pas. L'authentification, la construction
d'URL, la limitation du débit et le backoff 429/503 conscient de Retry-After qu'un lecteur
doit avoir existent déjà comme module sans dépendance à lib/wp-http.js dans le répertoire
de cette compétence (le même module que le script de capture importe). Il exporte fetchJson,
buildHeaders, configureRateLimit et parseTotalHeader. Tout lecteur WordPress généré
doit réutiliser ce module plutôt que de réimplémented le transport, pour que le lecteur ne
contienne que l'orchestration par projet : quelles entités extraire, la boucle de pagination,
la résolution de _embed/_links et le collage de transformation. Un noyau de transport testé
est ce qui rend l'échantillonneur et le lecteur se comportent identiquement. La façon dont le
module est porté dans un projet de migration exécutable est la préoccupation de rp-import-codegen
(ses cibles File), pas celle de cet adaptateur. Les notes ci-dessous décrivent ce que le lecteur
fait en plus de ce noyau partagé :
- Les espaces de noms et l'authentification diffèrent par espace de noms :
wp/v2(core) : authentification HTTP Basic avec un Application Password WordPress (--username+--application-password).wc/v3(WooCommerce) : clé consommateur / secret, envoyés comme authentification Basic sur HTTPS (ou comme paramètres de requête sur certains hôtes). Ceci est un identifiant différent du Application Password — tous deux peuvent être nécessaires pour une migration complète.
- Pagination :
?page=N&per_page=M(leper_pagemax est typiquement 100). Le total de pages est dans l'en-tête de réponseX-WP-TotalPageset le total d'enregistrements dansX-WP-Total— lisez ceux-ci plutôt que de deviner quand arrêter. - Relations intégrées : demandez
?_embedpour intégrer les ressources liées, ou suivez le bloc_links(author,wp:featuredmedia,wp:term) pour résoudre les relations. Les pointeursevidencedans les relations desource-schema.jsonproviennent de ce bloc_links. - Taxonomies hiérarchiques : les catégories WordPress (et les taxonomies hiérarchiques
personnalisées) ont un champ
parentsur chaque terme (0= top-level). Quand n'importe quel terme a unparentnon-zéro, la taxonomie source est imbriquée. La découverte doit élever ceci dans le schéma structuré — définissez"hierarchical": truesur cette entité danssource-schema.json(voirsource-schema.example.json→category) plutôt que de laisserparententerré dans la dump brute. La cible de catégorie Blog Wix est plate (FR-006), donc cet indicateur est ce qui déclenche l'entrée de perte obligatoire du mappeur ; sans lui, l'aplatissement se produit silencieusement. - Limites de débit / retries : non annoncées ; le script de capture limite
(
--rate-limit-rpm, par défaut 120) et recule sur 429/503 en honorantRetry-After. Les lecteurs générés doivent hériter de la même discipline. - Contenu enrichi :
content.rendered/title.renderedsont du HTML ;*.rawnécessitecontext=edit(authentifié). Notez lequel le lecteur doit extraire. - Champs personnalisés : ACF / meta apparaissent souvent dans les enregistrements
échantillons mais sont absents du schéma
OPTIONS— surfacez-les commeunknownsen découverte pour que le mappeur puisse décider.
Forme du schéma
source-schema.example.json (dans le dossier de cette compétence) est le modèle que
rp-discovery suit lors de l'émission de migrations/<project>/source-schema.json. C'est
une forme à suivre, pas un schéma strict à valider. Gardez le noyau agnostique vis-à-vis de
la plateforme stable ; poussez les particularités WordPress (restNamespace, statuses, etc.)
dans le blob ouvert sourceMeta de chaque entité.