← back to Flock Fix Viewer
fix-unit.mjs
44 lines
// Fix flock unit_of_measure: single roll (NOT double), ships untrimmed. Reversible + ledgered.
import fs from 'fs'; import os from 'os'; import path from 'path';
const SHOP='designer-laboratory-sandbox.myshopify.com';
const TOKEN=fs.readFileSync(new URL('./.token',import.meta.url),'utf8').trim();
const LEDGER=path.join(os.homedir(),'.claude/yolo-queue/executed-reversible/ledger.jsonl');
const DRY=!process.argv.includes('--apply');
const NEWVAL='Priced Per Single Roll. Ships untrimmed (30" untrimmed / 27" trimmed width).';
async function gql(q,v={}){const r=await fetch(`https://${SHOP}/admin/api/2024-10/graphql.json`,{method:'POST',headers:{'X-Shopify-Access-Token':TOKEN,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v})});return r.json();}
const sleep=ms=>new Promise(r=>setTimeout(r,ms));
const Q=`query($c:String){ products(first:100, query:"(tag:'Flock Velvet' OR title:flock OR handle:flock)", after:$c){
pageInfo{hasNextPage endCursor}
edges{node{ id handle status variants(first:6){edges{node{title price}}}
uom: metafield(namespace:"global",key:"unit_of_measure"){value} }}
}}`;
const SETMF=`mutation($mf:[MetafieldsSetInput!]!){ metafieldsSet(metafields:$mf){ userErrors{field message} } }`;
(async()=>{
let cur=null,all=[];
do{const r=await gql(Q,{c:cur});const p=r?.data?.products;if(!p){console.error(JSON.stringify(r));break;}all=all.concat(p.edges);cur=p.pageInfo.hasNextPage?p.pageInfo.endCursor:null;}while(cur);
const targets=all.map(e=>e.node).filter(n=>{
if(n.status==='ARCHIVED') return false;
const roll=n.variants.edges.map(e=>e.node).filter(v=>!/sample/i.test(v.title||''));
const priced=roll.some(v=>parseFloat(v.price)>10);
const cur=(n.uom&&n.uom.value)||'';
return priced && /double/i.test(cur); // only ones still saying "double"
});
console.log(`priced flock with 'double roll' language: ${targets.length}`);
if(DRY){targets.slice(0,10).forEach(n=>console.log(' ',n.handle,'::',n.uom.value));return;}
let done=0;
for(const n of targets){
const prior=(n.uom&&n.uom.value)||'';
const r=await gql(SETMF,{mf:[{ownerId:n.id,namespace:'global',key:'unit_of_measure',type:'single_line_text_field',value:NEWVAL}]});
const errs=r?.data?.metafieldsSet?.userErrors;
if(errs&&errs.length){console.log(' FAIL',n.handle,JSON.stringify(errs));continue;}
done++;
fs.appendFileSync(LEDGER,JSON.stringify({ts:new Date().toISOString(),agent:'main:flock-unit-fix',ticket:'flock-single-roll',
action:`unit_of_measure -> single roll (not double) on ${n.handle}`,blast_radius:1,
undo_cmd:`metafieldsSet global.unit_of_measure = ${JSON.stringify(prior)}`,verify:`uom no longer says 'double'`})+'\n');
await sleep(250);
}
console.log(`DONE · fixed ${done}`);
})();