← back to Hollywood Import

fix-real-vendor.mjs

45 lines

// fix-real-vendor.mjs — corrective pass over the 366 DWHD products written by
// backfill-specs.mjs on 2026-07-15: dwc.real_vendor was set to the BRAND
// ("Hollywood Wallcoverings"); the field's contract is the TRUE upstream vendor,
// which for the DWHD/momentum_colorways line is Momentum (Steve 2026-07-15).
// Scope is ONLY the backfill-targets.json pids — legacy X**-prefix Hollywood
// products have mixed/unknown upstream sources and are untouched.
// Batched 25 owners per metafieldsSet call. $0 — Admin API only.
import fs from 'node:fs';

const env = fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env', 'utf8');
const STORE = (env.match(/^SHOPIFY_STORE=(.+)$/m) || [])[1].trim();
const TOKEN = (env.match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m) || [])[1].trim();
const GQL = `https://${STORE}/admin/api/2024-10/graphql.json`;
const H = { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' };
const APPLY = process.argv.includes('--apply');
const sleep = ms => new Promise(r => setTimeout(r, ms));

const M_SET = `mutation($mf:[MetafieldsSetInput!]!){metafieldsSet(metafields:$mf){userErrors{field message}}}`;
const items = JSON.parse(fs.readFileSync(new URL('backfill-targets.json', import.meta.url).pathname, 'utf8'));
const pids = [...new Set(items.map(it => Number(String(it.shopify_id).match(/\d+$/)[0])))];
console.log(`fix-real-vendor: ${pids.length} products → dwc.real_vendor = "Momentum" · ${APPLY ? 'APPLY' : 'DRY-RUN'}`);
if (!APPLY) { console.log('sample pids:', pids.slice(0, 5).join(', ')); process.exit(0); }

let done = 0, err = 0;
for (let i = 0; i < pids.length; i += 25) {
  const batch = pids.slice(i, i + 25).map(pid => ({
    ownerId: `gid://shopify/Product/${pid}`,
    namespace: 'dwc', key: 'real_vendor',
    type: 'single_line_text_field', value: 'Momentum',
  }));
  try {
    const r = await fetch(GQL, { method: 'POST', headers: H, body: JSON.stringify({ query: M_SET, variables: { mf: batch } }) });
    const j = await r.json();
    if (j.errors) throw new Error(JSON.stringify(j.errors).slice(0, 200));
    const ue = j.data.metafieldsSet.userErrors;
    if (ue.length) { console.error(`  batch@${i} userErrors: ${JSON.stringify(ue).slice(0, 200)}`); err += ue.length; }
    done += batch.length - ue.length;
    console.log(`  … ${Math.min(i + 25, pids.length)}/${pids.length}`);
    await sleep(800);
  } catch (e) {
    console.error(`  batch@${i} ERR: ${e.message.slice(0, 160)}`); err += batch.length; await sleep(1500);
  }
}
console.log(`DONE: set=${done} err=${err}`);