rp-source-shopify

Par wix · skills

Adaptateur de source de données privées Shopify, lu entièrement via le Shopify CLI (`shopify store execute`) sur la machine de l'opérateur d'import : capture de découverte, sa séquence d'étapes reprenables, les lignes de couverture de source, l'extraction bulk du store complet, et le contrat de lecture pour le codegen. À utiliser quand la plateforme source est Shopify et que l'Admin API (données privées) a été choisie. La route storefront public est `rp-quick-shopify` / contenu public, pas ce skill.

npx skills add https://github.com/wix/skills --skill rp-source-shopify

rp-source-shopify

Adaptateur source Shopify source adapter pour données privées : commandes, clients, cartes cadeaux, réductions, produits brouillon et archivés, contenu, navigation, emplacements, expédition, métaobjets, fichiers et redirections. Il suit le même contrat que rp-source-wordpress et rp-source-csv : il découvre ce que contient le magasin, écrit les fichiers de découverte standard, enregistre tout ce qu'il n'a pas pu capturer sous forme de ligne source-coverage, et cède la main aux étapes générales de mapping, approbation, import et reporting. Rien de ce qu'il lit n'est réécrit ; le magasin n'est jamais modifié.

Quand cette skill est utilisée

  • rp-discovery exécute la section Discovery quand la réponse du mode d'acquisition Shopify est Admin API (sourceMode=private_data).
  • rp-import-codegen lit la section Read contract.

Chemin d'accès : la Shopify CLI, lecture seule

Chaque appel est store execute --store <shop>.myshopify.com --query <query> --json --version 2026-10, exécuté via lib/shopify-cli.js par l'installation Shopify CLI propre de l'adaptateur, en utilisant la session que l'opérateur a approuvée dans le navigateur sur sa machine. Aucun token n'est stocké par cet adaptateur.

  • Lecture seule par construction. Un document de mutation est refusé avant le démarrage de tout processus. L'unique exception est le démarrage de l'extraction en masse : Shopify classe bulkOperationRunQuery (un travail de lecture) comme une mutation, donc startBulkOperation envoie ce document fixe unique avec --allow-mutations. Aucun autre appel ne peut porter le flag, et les opérations ne sont jamais annulées.
  • Une erreur GraphQL est une donnée sur le magasin, retournée à l'appelant : la découverte la transforme en ligne de coverage capture-failed. Une lecture Shopify qui s'étrangle sur les 6 appels (1, 2, 4, 8, 16 s entre eux) devient shopify_throttled, également une ligne capture-failed à la découverte. Tout autre échec CLI arrête l'étape (exit 2) ; il n'est jamais réessayé en boucle et jamais lu comme « aucun enregistrement ».
  • Les conditions Shopify interdisent d'automatiser l'admin du magasin dans un navigateur. Ne le faites jamais.

La connexion : un compte staff dédié, vérifié avant chaque lecture

Entrées : SHOPIFY_SHOP_DOMAIN=<shop>.myshopify.com dans config/source.shopify.env (pas un secret). Node.js de l'opérateur doit être 22.12 ou ultérieur.

  1. Le propriétaire du magasin crée un compte staff pour la migration (rôle Administrator, ou un rôle personnalisé avec gestion des apps et des canaux) et le confie à l'opérateur d'import. Le compte du propriétaire lui-même n'est pas un secours autorisé.

  2. Exécutez la vérification de session depuis le répertoire de cette skill :

    node scripts/shopify-session-check.js --project <migrations-root>/<project>

    Elle vérifie, dans l'ordre et s'arrête au premier échec : Node.js ≥ 22.12 ; la CLI Shopify propre de l'adaptateur à la version exacte 4.8.3 dans ~/.replatform/tools/shopify-cli-4.8.3 ; la connexion et la relecture des scopes Shopify (chaque scope que les lectures déclarent) ; et que Shopify liste la version Admin API épinglée 2026-10 comme supportée. Ensuite, elle écrit data/shopify-discovery/session-receipt.json (pas de secret, pas de donnée personnelle).

  3. La première fois, elle pose la première question de connexion (une action discovery question) : la connexion a-t-elle été approuvée depuis le compte staff de migration dédié ? Répondez dedicated-account uniquement si c'est le cas. other-account arrête : la découverte ne démarre pas et la question est posée à nouveau après que le propriétaire fournisse un compte dédié.

  4. Suivez ses codes d'arrêt :

Code Ce que fait l'opérateur
shopify_cli_node_unsupported Nécessite Import Operator. Basculez ce terminal vers Node.js 22.12 ou ultérieur (par exemple la LTS actuelle) avec l'installateur ou le gestionnaire de versions habituel, vérifiez node --version, exécutez la vérification à nouveau. Rien n'a été installé ou lu
shopify_cli_not_installed / shopify_cli_version_changed Demandez à l'opérateur ; avec son consentement, réexécutez la vérification avec --install (installe ou réinstalle exactement 4.8.3 dans le dossier de l'adaptateur, environ 52 MB, rien de global)
shopify_session_missing / shopify_scopes_missing Exécutez la vérification avec --connect et approuvez dans le navigateur en étant connecté au magasin en tant que compte staff dédié. --connect demande la liste complète des scopes dérivés
shopify_cli_incompatible L'installation de l'adaptateur est endommagée ou a été déplacée ; réinstallez avec --install
shopify_api_version_unsupported Arrêtez et signalez : déplacer l'épingle est un changement de code testé, jamais un contournement

N'écrivez jamais shopify store auth ou toute autre commande shopify nue. --connect démarre l'approbation du navigateur lui-même via la CLI de l'adaptateur avec la mise à jour automatique Shopify désactivée ; une commande nue exécuterait une autre CLI Shopify et pourrait mettre à niveau une installation à l'échelle de la machine. N'exécutez jamais npm -g, shopify config autoupgrade, ou ne changez aucun paramètre CLI Shopify.

Codes de sortie : 0 réussi et confirmé ; 3 la première question de connexion est en attente ; 2 arrêté (le code imprimé indique pourquoi) ; 1 erreur d'usage.

Exécutez la vérification avant la découverte et avant chaque extraction. La découverte refuse de démarrer (shopify_session_not_checked, shopify_first_connection_unconfirmed) jusqu'à ce que la dernière vérification pour ce magasin soit réussie et que la réponse à la première connexion soit dedicated-account.

Quand la connexion expire

Une lecture dont la session CLI a expiré arrête l'étape avec source_auth_expired et crée une action utilisateur manual_action pour la phase (discovery ou execution) ; l'exécution s'immobilise à awaiting_user_action. Nécessite Import Operator : exécutez la vérification de session (avec --connect si demandé), puis répondez à la demande et réexécutez la même étape. Seul le reçu change, donc l'étape reprend où elle s'était arrêtée et aucune lecture terminée n'est répétée.

Le compte staff après le basculement

La première vérification réussie après une réponse dedicated-account enregistre le compte dans data/shopify-discovery/staff-access.json. À partir de là, chaque rapport de fin énumère shopify-staff-account-removal (haute priorité) jusqu'à ce que la suppression du propriétaire soit enregistrée :

node scripts/shopify-session-check.js --project <dir> --confirm-staff-removal owner-removed-account

Supprimez le compte uniquement après le basculement et après la dernière lecture depuis Shopify (y compris toute mise à jour). Si la confirmation signale que l'enregistrement est illisible ou manquant, exécutez d'abord --repair-staff-access : il met le fichier endommagé de côté, reconstruit une entrée pending et n'écrit jamais confirmed. Rien d'autre ne ferme l'action ; ne modifiez jamais le fichier à la main.

Découverte

Exécutez depuis le répertoire de cette skill :

node scripts/shopify-discovery.js --project <migrations-root>/<project> --store <shop>.myshopify.com

Les étapes s'exécutent dans cet ordre. Chacune enregistre son résultat dans data/shopify-discovery/discovery-steps.json avant que la suivante ne démarre, donc un redémarrage n'exécute que les étapes non encore enregistrées et ne relit aucune entité déjà capturée :

Étape Ce qu'elle fait Écrit
capture Un décompte (quand l'API en a un) et jusqu'à 3 enregistrements d'exemple par entité, plus le magasin et ses politiques entities/<entity>.json
withheld-details Huit sondes ordinaires de 3 enregistrements classent les types de nom, email, téléphone et adresse retenus pour les clients et commandes kind-probes.json
gift-card-census Recensement des cartes cadeaux avec limite de décompte exact ; chaque solde positif est dû bulk-manifest.json, gift-card-census.json
order-window Commandes plus anciennes que la fenêtre d'historique des commandes ~60 jours de la CLI (ci-dessous) order-window.json
questions Demande au marchand ce que les étapes antérieures n'ont pas pu lire, en tant qu'actions utilisateur discovery question réponses orchestration/user-actions/*.json
coverage Crée les lignes de coverage et écrit l'index de capture brute source-coverage.json, README.md

⚠️ Quand ce bundle ne fournit pas l'implémentation d'une étape, la découverte s'arrête à cette étape avec shopify_discovery_step_unavailable (exit 2) après avoir enregistré les étapes antérieures. Ne contournez pas : une découverte qui a sauté la vérification paraîtrait complète tout en manquant des données. Signalez-le à l'utilisateur.

Codes de sortie : 0 complète ; 3 une question du marchand est en attente — l'exécution s'immobilise à awaiting_user_action ; répondez-y, puis réexécutez la même commande (rien n'est relu) ; 2 arrêtée, avec le code de raison en JSON imprimé ; 1 erreur d'usage.

Pour relire les entités après que leur accès soit rétabli, ajoutez --reread <entity> (répétable). Seules ces entités sont relues ; le fichier de coverage est reconstruit.

Un magasin par capture. Le magasin est enregistré dans discovery-steps.json et dans chaque entities/<entity>.json avant toute lecture. Une exécution pour tout autre --store s'arrête avec shopify_discovery_store_mismatch (exit 2) avant de lire ou modifier quoi que ce soit, donc aucun artefact ne combine jamais deux magasins. --restart abandonne toute la capture data/shopify-discovery/ (étapes, entités, tous les fichiers techniques des étapes, fichier de coverage, index) et relit à partir de zéro ; il conserve les enregistrements de connexion (session-receipt.json, staff-access.json). Elle est refusée avec shopify_restart_blocked_handoff quand ce projet remet déjà un magasin différent au mapping — source-profile.md, source-schema.json ou la discovery/source-coverage.json promue existe — car ceux-ci continueraient de présenter le premier magasin : démarrez plutôt un nouveau projet de migration pour l'autre magasin. Elle refuse aussi avec shopify_restart_blocked tant qu'une question du marchand de la capture antérieure reste sans réponse. Ne supprimez jamais de fichiers à la main pour contourner une discordance.

Fenêtre d'historique des commandes

Via la CLI, Shopify n'affiche que les ~60 derniers jours de commandes, sur chaque chemin de lecture. L'étape order-window lit shop.createdAt :

  • magasin plus ancien que la fenêtre, ou createdAt illisible → ligne shopify:orders-before-window ;
  • magasin plus récent que la fenêtre → elle lit la commande visible avec le processedAt le plus ancien ; une commande traitée avant la création du magasin (historique importé) → la ligne, pas de question ; sinon, elle demande au marchand « Des commandes ont-elles été importées dans ce magasin Shopify depuis un autre système ? » (no → pas de ligne ; yes ou unknown → la ligne).

N'utilisez jamais les dates des commandes visibles comme preuve de complétude. La ligne est auth-gated / requires-development, immobilise l'exécution au mapping jusqu'à ce qu'elle ait une disposition, et la perte est acceptée uniquement via une porte loss-accepted.

Détails client et commande retenus

L'étape withheld-details envoie une requête ordinaire par entité et type protégé. Un type est retenu uniquement quand Shopify retourne un chemin d'erreur nommant l'un des champs de ce type. Un blanc sans erreur est le blanc du marchand ; la politique acceptée n'ajoute délibérément aucun recensement de magasin complet. Un ACCESS_DENIED sans chemin, un chemin non lié ou un autre échec produit shopify:<entity> capture-failed, jamais un type deviné. Un refus sans chemin revérifie d'abord la session et permet au maximum une réapprobation.

kind-probes.json enregistre uniquement les résultats, chemins et codes d'erreur, plus la projection par entité ; il n'enregistre jamais les valeurs client. Chaque sonde complétée est atomique, donc le redémarrage envoie uniquement les sondes manquantes. --reread customers ou --reread orders efface aussi les sondes de cette entité.

L'extraction supprime exactement les champs du type retenu des requêtes client et commande. Le nom est prénom/nom ; l'adresse est les lignes d'adresse, code postal et géolocalisation. La société, ville, province, pays et tout autre champ explicitement non protégé restent. Un client est écrit dans customers-withheld-identity.ndjson, pas customers.ndjson, uniquement quand un type d'identité est retenu et qu'aucun nom, email ou téléphone lisible ne reste. Le manifeste enregistre withheldIdentityCount, et la vérification du décompte inclut le fichier annexe.

Cartes cadeaux : les codes ne bougent jamais, les soldes restent dus

Shopify n'expose que lastCharacters et maskedCode, jamais un code complet réutilisable. Ne créez jamais une carte cadeau Wix dépensable à partir de cette lecture. Le recensement et chaque extraction exécutent la même requête en masse, puis la verrouillent avant done avec giftCardsCount(limit: null) lié au createdAt de la lecture. Seul precision: EXACT avec au moins autant de cartes lues réussit. Un décompte court ou inexact, un filtre rejeté, ou un montant en décimal brut invalide échoue l'entrée et enregistre shopify:gift-cards ; l'extraction reste arrêtée jusqu'à ce que --retry-failed démarre une nouvelle lecture.

Chaque solde positif est dû, y compris les cartes désactivées et les cartes portant une date d'expiration. L'argent est additionné exactement par devise sans point flottant ou conversion. Le recensement ne conserve que les décomptes, totaux par devise, décomptes désactivés/expirés et preuves de lecture ; il ne stocke aucun id de carte, code masqué ou valeur client. Un recensement non vide émet shopify:gift-card-codes. Si des cartes apparaissent pour la première fois pendant l'extraction, cette ligne est ajoutée et l'extraction s'arrête pour que le mapping décide.

Entités lues

products (tous statuts, avec variantes), collections, orders (avec remboursements et exécutions), customers, gift-cards, discounts, pages, blogs, articles, menus, locations, inventory-items, delivery-profiles, metaobjects (listées via leurs définitions, chacune avec son décompte), files, url-redirects, et les singletons shop et shop-policies. lib/discovery-reads.js contient chaque requête nommée.

Synthétiser, puis promouvoir

Après la sortie du script 0, synthétisez source-profile.md et la source-schema.json racine du projet à partir de data/shopify-discovery/entities/*.json, en suivant source-schema.example.json dans ce répertoire. Par entité :

  • rawFile est entities/<entity>.json ; recordCount est son count uniquement quand son countExact est true (Shopify a répondu precision: EXACT). Sinon recordCount est null : quand l'API n'a pas de décompte, dites-le ; quand le décompte est une limite inférieure (countPrecision: "AT_LEAST"), mettez-le dans recordCountAtLeast et n'écrivez jamais recordCount. N'inventez jamais un décompte. inUse est true quand des exemples ont été retournés.
  • Une entité dont le fichier porte errors[] n'est pas synthétisée comme une entité vide : c'est une ligne de coverage déjà.
  • Enregistrez dans source-profile.md : l'accès est la session Shopify CLI de l'opérateur, lecture seule ; la CLI affiche uniquement les commandes récentes ; la devise et le fuseau horaire du magasin depuis le singleton shop.

Puis promouvoir, depuis rp-discovery :

node scripts/promote-source-coverage.js <migrations-root>/<project> --adapter shopify

Extraction

Le magasin complet est lu via l'export en masse côté serveur Shopify, un dataset à la fois, jamais page par page. Exécutez depuis le répertoire de cette skill, après la vérification de session :

node scripts/shopify-extract.js --project <migrations-root>/<project> [--retry-failed] [--catch-up]

Le magasin vient de config/source.shopify.env (ou --store). Elle écrit data/source-extract/<entity>.ndjson — products, collections, customers, orders (les trois requêtes de commande jointes par id de commande : core, remboursements, exécutions), gift-cards-codeless, discounts, delivery-profiles, inventory-items, pages, blogs, articles, menus, url-redirects, locations, metaobjects, files — plus l'optionnel customers-withheld-identity.ndjson — et data/source-extract/extract-manifest.json. Les 18 requêtes en masse et huit requêtes ordinaires probe-*.graphql commencent chacune par une ligne # scopes: dont la vérification de session dérive les scopes requis. Les commandes et clients sont filtrés au moment snapshot du manifeste T.

  • Une opération à la fois, dans l'ordre du tableau. Chaque changement d'état est une écriture de manifeste atomique unique (pending → starting → running → downloaded → done, ou settling → failed | denied), donc un redémarrage reprend exactement à cet état et un dataset terminé n'est jamais relu. Un dataset dont le démarrage a été interrompu est simplement redémarré ; le résultat du premier travail n'est jamais lu.
  • Seul un téléchargement complet compte. Un fichier est downloaded uniquement pour HTTP 200, exactement fileSize octets, se terminant par une nouvelle ligne, chaque ligne un objet JSON. Un lien expiré (HTTP 400 ou 403) relance le dataset (au maximum 2 fois) ; les autres échecs téléchargent à nouveau (3 essais), puis un relancement, puis failed.
  • Une opération échouée, expirée, annulée ou partielle est relancée une fois, puis failed (shopify_bulk_failed). Un dataset d'extraction failed arrête l'extraction maintenant et à chaque démarrage ultérieur. ACCESS_DENIED exécute d'abord la vérification de session ; un refus avec une session valide est final pour ce dataset (les requêtes client et commande vont à l'attribution de détails retenus de la spécification client/commande ; chaque autre dataset est failed).
  • Attribution de refus client/commande. Un refus en masse à session valide entre dans settling, puis exécute les quatre sondes ordinaires de cette entité. Un type retenu nouvellement nommé est insertionné et promu comme sa propre ligne de coverage et s'arrête avec shopify_protected_fields_withheld ; après le mapping, la requête refusée se réinitialise avec la projection plus étroite. Un diagnostic tout lisible, sans chemin ou non lié est unattributed, laisse la projection inchangée et arrête chaque démarrage avec shopify_bulk_failed jusqu'à --retry-failed. Chaque diagnostic est clé par requête et settlingAt, donc la relecture du gestionnaire n'envoie jamais une sonde terminée ou duplique une ligne.
  • settling rend les conséquences récupérables : l'erreur verbatim est écrite d'abord, puis le gestionnaire idempotent du résultat (la ligne de coverage), puis l'état terminal. Un redémarrage réexécute le gestionnaire de tout dataset settling avant toute autre chose.
  • Retard. Un travail encore en préparation 4 heures après son démarrage crée une action utilisateur question (choices wait / abort) et l'étape s'immobilise à awaiting_user_action (exit 3). Répondez-y et réexécutez la même commande. abort rend le dataset failed (shopify_bulk_overdue_aborted) ; l'opération Shopify n'est pas annulée.
  • Vérification du décompte. Après la lecture, les clients (plus le fichier d'identité retenue) et les commandes doivent atteindre le décompte exact de Shopify à T. Moins, ou un décompte que Shopify ne donne que comme AT_LEAST, est une ligne capture-failed shopify:<entity> (via les règles lib/import-findings.js) et l'arrêt shopify_extract_count_short / shopify_extract_count_inexact ; l'exécution revient au mapping. Une lecture est une photo du magasin pendant son exécution, pas un snapshot figé.
  • Porte de carte cadeau. Tant que gift-cards est encore downloaded, son décompte exact et chaque montant en décimal sont vérifiés. Seul un succès écrit le fichier sans code par lecture nommé par cardsFile, enregistre les décomptes dus et soldes dans le manifeste, et permet done. Les fichiers qu'aucune entrée done ne nomme sont ignorés. gift-cards-codeless.ndjson ne contient pas maskedCode et n'est jamais un fichier d'import de carte cadeau Wix.
  • --retry-failed (Import Operator) : envoie chaque dataset d'arrêt — chaque entrée failed, chaque entrée denied non attribuée, et les datasets dont la vérification du décompte a arrêté l'extraction — au statut pending et les relit. Rien d'autre n'est réinitialisé.
  • --catch-up (la réexécution de mise à jour source) : archive un manifeste complete comme extract-manifest.<T_prev>.json et relit le magasin complet en totalité avec un nouveau T. Un manifeste qui n'est pas complet est repris à la place. Sans le flag, un manifeste complete avec ses fichiers finaux présents ne relit rien.

Codes de sortie : 0 complète ; 3 une question retardée est en attente ; 2 arrêtée (le code imprimé indique pourquoi ; les datasets terminés sont conservés) ; 1 erreur d'usage. Les codes d'arrêt sont dans rp-execute-import. Un manifeste lié à un autre magasin s'arrête avec shopify_extract_store_mismatch.

Basculement — relecture finale. Chaque import laisse une tâche : après l'arrêt de l'activité Shopify du marchand (et avant la suppression du compte staff), exécutez la vérification de session, puis la réexécution pour les enregistrements nouveaux et modifiés, qui exécute shopify-extract.js --catch-up. Vérifiez que extract-manifest.json dit complete, que chaque readAt de chaque entrée est après l'arrêt de l'activité, et que la réexécution est terminée. Nécessite Import Operator.

Basculement — export de détails retenus. Toute ligne de type retenu ou de client creux garde aussi la haute action d'achèvement shopify-withheld-details-export ouverte, quelle que soit sa disposition de mapping. Après la mise à jour finale et après que le marchand exporte les clients et commandes depuis Shopify Admin, enregistrez l'attestation dans l'environnement de migration d'origine :

node scripts/shopify-discovery.js --project <migrations-root>/<project> --confirm-withheld-export owner-exported

Régénérez le rapport d'achèvement et vérifiez que l'action est partie. Une future lecture Shopify ou une nouvelle ligne retenue la rouvre. Ceci est une attestation d'opérateur, pas une vérification Shopify. L'intégration future 0197/0198 mise à jour/checklist n'est pas câblée ; le rapport d'achèvement est la remise durable. Nécessite Import Operator.

Basculement — soldes de cartes cadeaux dus. Le rapport d'achèvement réévalue toujours l'action haute shopify-gift-card-codes-not-migrated quand shopify:gift-card-codes existe, même après l'acceptation de sa perte. Nécessite Import Operator :

node scripts/shopify-gift-card-remedy.js export --project <project>
node scripts/shopify-gift-card-remedy.js activity-stopped --project <project> --at <ISO-time> --by <name>
# Exécutez ici la relecture finale --catch-up.
node scripts/shopify-gift-card-remedy.js record-replacements --project <project> --evidence <file.csv> --by <name>
# Ou enregistrez la date encore ouverte à laquelle Shopify cessera de les accepter :
node scripts/shopify-gift-card-remedy.js keep-redeeming --project <project> --until <YYYY-MM-DD> --by <name>

export écrit data/shopify-cutover/gift-cards-owed.csv avec id, derniers caractères, solde, devise, activé, expiration et état actuellement remplacé — aucune colonne code ou client. Une carte se ferme uniquement quand le manifeste actuel a une lecture réussie lancée après activity-stopped, et son preuve CSV nomme un remplacement Wix valant au moins le solde de cette carte dans la même devise plus une date de notification du titulaire non future et un confirmant. Une carte plus récente ou solde plus élevé rouvre cette carte ; une lecture en attente/échouée ou enregistrement d'arrêt d'activité plus récent rouvre toutes. Garder Shopify acceptant n'est jamais une fermeture.

Lignes de coverage

L'adaptateur écrit toujours data/shopify-discovery/source-coverage.json (platform: "shopify", adapter: "shopify"), avec rows: [] quand il n'y a rien à signaler. Les lignes sont décidées au mapping comme les lignes de toute source.

coverageId Quand reason recoverability
shopify:<entity> Une lecture de découverte de cette entité a échoué capture-failed import-operator
shopify:<entity> Une lecture étranglée, une sonde de champ protégé non attribuée, un dataset d'extraction échoué ou retardé-avorté, ou une lecture complète inférieure au décompte de Shopify capture-failed import-operator
shopify:orders-before-window Des commandes plus anciennes que la fenêtre CLI peuvent exister (étape order-window) auth-gated requires-development
shopify:customer-<kind>, shopify:order-<kind> (name, email, phone, address) Un chemin d'erreur de sonde ordinaire nomme ce type retenu auth-gated requires-development
shopify:customers-withheld-identity Au moins un client extrait n'a aucune identité lisible après projection auth-gated requires-development
shopify:gift-card-codes Les codes de cartes cadeaux ne sont jamais lisibles route-unsupported not-recoverable

capability est la chaîne du registre où l'une existe (commerce.orders, crm.contact, commerce.gift-cards, commerce.catalog-product, …) ; sinon null avec capabilityUnregistered: true. ⚠️ Une ligne ne porte aucun champ count ; les décomptes restent dans les fichiers d'entités et la evidence de la ligne les pointe.

Contrat de lecture

Pour rp-import-codegen quand source-schema.json.platform === "shopify" :

  • Fournissez lib/shopify-cli.js et lisez uniquement via celui-ci, avec ses défauts (CLI propre de l'adaptateur, CI=1, --version 2026-10) ; ne passez jamais command ou env. Pas de HTTP direct, aucun token stocké, jamais --allow-mutations pour une lecture. Les exemples de découverte et les décomptes paginent avec readAllPages (first: 250, 500 ms entre deux) ; une lecture de magasin complet ne fait jamais cela.
  • Exécutez la vérification de session avant chaque extraction. Sur source_auth_expired, appelez lib/shopify-session.js recordAuthExpired(projectDir, { stage: 'execution', store }) et arrêtez ; l'extraction reprend depuis son manifeste après réapprobation.
  • L'extraction complète du magasin est l'extracteur en masse de l'adaptateur (scripts/shopify-extract.js, ci-dessus), pas un pageur par enregistrement généré : générez l'importateur pour lire data/source-extract/<entity>.ndjson uniquement quand extract-manifest.json dit complete. Si ce bundle ne le fournit pas, arrêtez la génération de code et signalez-le.
  • Une lacune détectée d'abord lors de l'extraction est enregistrée avec lib/import-findings.js stopWithFinding(projectDir, { row, code }) : la ligne est ajoutée au fichier de coverage brut par coverageId (remplaçant une ligne avec le même id), le fichier est ré-promu, et l'extraction s'arrête avec code. De là, l'exécution revient au mapping par le chemin général du pipeline, le même que pour toute source.

Pas dans cet adaptateur

  • Les apps installées et leurs données (avis, abonnements, points de fidélité) ne sont pas inventoriées ici.
  • Les exports CSV propres du marchand passent par rp-source-csv, une route séparée et dégradée.
  • La mise à jour finale reste la tâche source-catch-up partagée avec toute source. L'export de détails retenus et la suppression du compte staff sont suivis ici (ci-dessus) jusqu'à ce que la checklist de basculement les reprenne.

Skills similaires