← back to Hollywood Mfr Trim
trim.mjs
50 lines
#!/usr/bin/env node
// Trim whitespace on Hollywood (HWC) manufacturer_sku metafields (custom + dwc).
// Target: LIVE designer-laboratory-sandbox store. Dry-run unless --apply.
import fs from 'node:fs';
const APPLY = process.argv.includes('--apply');
const SHOP = 'designer-laboratory-sandbox.myshopify.com';
const API = '2024-10';
// pull token from the secrets .env
const envTxt = fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env', 'utf8');
const TOKEN = (envTxt.match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m) || [])[1]?.trim();
if (!TOKEN) { console.error('No SHOPIFY_ADMIN_TOKEN'); process.exit(1); }
const work = JSON.parse(fs.readFileSync(new URL('./worklist.json', import.meta.url), 'utf8'));
console.log(`Worklist: ${work.length} metafield writes across ${new Set(work.map(w=>w.ownerId)).size} products`);
console.log(APPLY ? '>>> APPLY MODE — writing to LIVE Shopify' : '>>> DRY RUN (no writes). Pass --apply to execute.');
if (!APPLY) {
for (const w of work) console.log(` ${w.ownerId.split('/').pop()} ${w.namespace}.${w.key} -> "${w.value}"`);
console.log(`\nDry run complete. ${work.length} writes staged.`);
process.exit(0);
}
const MUT = `mutation($mf:[MetafieldsSetInput!]!){metafieldsSet(metafields:$mf){metafields{id namespace key value} userErrors{field message}}}`;
async function gql(variables){
const r = await fetch(`https://${SHOP}/admin/api/${API}/graphql.json`, {
method:'POST',
headers:{'Content-Type':'application/json','X-Shopify-Access-Token':TOKEN},
body: JSON.stringify({query:MUT, variables})
});
return r.json();
}
let ok=0, errs=[];
for (let i=0; i<work.length; i+=25){
const batch = work.slice(i, i+25);
const res = await gql({mf: batch});
const ue = res?.data?.metafieldsSet?.userErrors || [];
const set = res?.data?.metafieldsSet?.metafields || [];
if (res.errors) { errs.push(JSON.stringify(res.errors)); console.error('GraphQL error', res.errors); }
if (ue.length) { errs.push(...ue.map(e=>JSON.stringify(e))); console.error('userErrors', ue); }
ok += set.length;
console.log(` batch ${i/25+1}: set ${set.length}/${batch.length}`);
await new Promise(r=>setTimeout(r, 600)); // gentle rate limit
}
console.log(`\nDone. ${ok}/${work.length} metafields set. Errors: ${errs.length}`);
if (errs.length) process.exit(1);