← back to Tk10630 Sku Suffix Canary
backfill-xwh-meta.mjs
41 lines
// Backfill dw_sku metafields = real XWH-<n> mfr code for EVERY live XWH product
// (both vendor labels), wherever the metafield is missing or wrong. Metafield-only
// (write_products, default token). READ-then-WRITE, idempotent.
import { gql } from './shopify.mjs';
const APPLY = process.argv.includes('--apply');
const products = new Map();
let cursor = null;
while (true) {
const q = `query($c:String){ productVariants(first:200, query:"sku:XWH-*", after:$c){
pageInfo{ hasNextPage endCursor }
nodes{ sku product{ id handle status
g:metafield(namespace:"global",key:"dw_sku"){value}
d:metafield(namespace:"dwc",key:"dw_sku"){value}
variants(first:10){ nodes{ sku } } } } } }`;
const { data } = await gql(q, { c: cursor });
for (const n of data.productVariants.nodes) products.set(n.product.id, n.product);
if (!data.productVariants.pageInfo.hasNextPage) break;
cursor = data.productVariants.pageInfo.endCursor;
}
const MFS = `mutation($m:[MetafieldsSetInput!]!){ metafieldsSet(metafields:$m){ metafields{id} userErrors{field message} } }`;
let need = 0, done = 0, err = 0;
for (const p of products.values()) {
let base = null;
for (const v of p.variants.nodes) { const m = (v.sku || '').match(/^(XWH-\d+)/); if (m) { base = m[1]; break; } }
if (!base) continue;
const targets = [];
if (p.g?.value !== base) targets.push({ ownerId: p.id, namespace: 'global', key: 'dw_sku', type: 'single_line_text_field', value: base });
if (p.d?.value !== base) targets.push({ ownerId: p.id, namespace: 'dwc', key: 'dw_sku', type: 'single_line_text_field', value: base });
if (!targets.length) continue;
need++;
if (APPLY) {
try { const { data } = await gql(MFS, { m: targets }); const ue = data.metafieldsSet.userErrors; if (ue.length) { err++; console.log('✗', p.handle, JSON.stringify(ue)); } else done++; }
catch (e) { err++; console.log('✗', p.handle, e.message.slice(0, 100)); }
} else {
console.log(`would set ${p.handle} -> ${base} (${targets.length} mf)`);
}
}
console.log(`[backfill-xwh-meta] scanned=${products.size} need=${need} ${APPLY ? `done=${done} err=${err}` : '(dry-run)'}`);