← back to Flock Fix Viewer
nonastek-printtype.mjs
43 lines
// Non-Astek flock: set print_type=Flock (global+custom) on ACTIVE, genuinely-flock
// (title/handle contains "flock"), non-Phillipe-Romano products that lack it.
// Self-evident from the product's own stated construction. Reversible + ledgered. --apply to write.
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 SNAP=new URL('./nonastek-printtype-snapshot.json',import.meta.url);
const DRY=!process.argv.includes('--apply');
const API=`https://${SHOP}/admin/api/2024-10`;
const H={'X-Shopify-Access-Token':TOKEN,'Content-Type':'application/json'};
const sleep=ms=>new Promise(r=>setTimeout(r,ms));
const gql=async(q,v={})=>(await (await fetch(`${API}/graphql.json`,{method:'POST',headers:H,body:JSON.stringify({query:q,variables:v})})).json());
const Q=`query($c:String){ products(first:100, query:"tag:'Flock Velvet' -vendor:'Phillipe Romano' status:active", after:$c){
pageInfo{hasNextPage endCursor}
edges{node{ id handle title vendor
gpt:metafield(namespace:"global",key:"print_type"){value}
cpt:metafield(namespace:"custom",key:"print_type"){value}
}}}}`;
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 isFlock=n=>/flock/i.test(n.title)||/flock/i.test(n.handle);
const targets=all.map(e=>e.node).filter(n=>isFlock(n) && !(n.gpt?.value) && !(n.cpt?.value));
console.log(`ACTIVE non-PR genuine-flock lacking print_type: ${targets.length}`);
const snap=[];
let done=0;
for(const n of targets){
if(DRY){ if(done<12) console.log(' '+n.vendor.padEnd(22)+' '+n.title.slice(0,46)); done++; continue; }
const mf=[
{ownerId:n.id,namespace:'global',key:'print_type',type:'single_line_text_field',value:'Flock'},
{ownerId:n.id,namespace:'custom',key:'print_type',type:'single_line_text_field',value:'Flock'},
];
const r=await gql('mutation($mf:[MetafieldsSetInput!]!){metafieldsSet(metafields:$mf){userErrors{field message}}}',{mf});
const errs=r?.data?.metafieldsSet?.userErrors;
if(errs&&errs.length){console.log(' FAIL',n.handle,JSON.stringify(errs));continue;}
snap.push({id:n.id,handle:n.handle,old:{global_print_type:null,custom_print_type:null}});
fs.appendFileSync(LEDGER,JSON.stringify({ts:new Date().toISOString(),agent:'vp-dw-commerce:nonastek-flock-printtype',ticket:'TK-11128',action:`set print_type=Flock (global+custom) on ${n.handle} [${n.vendor}]`,blast_radius:1,undo_cmd:`metafieldsDelete global/custom.print_type on ${n.id} (old=null)`,verify:'PDP shows Print Type: Flock'})+'\n');
done++; if(done%10===0)console.log(` …${done}/${targets.length}`);
await sleep(200);
}
if(!DRY) fs.writeFileSync(SNAP,JSON.stringify(snap,null,1));
console.log(`${DRY?'DRY':'DONE'} · ${done} (${targets.length} targets)`);