← back to Jeffrey Stevens Margin Fix
pull-codes.mjs
27 lines
#!/usr/bin/env node
// READ-ONLY: pull live York code (custom.manufacturer_sku) + current sell/uom for the 882. Writes data/js882-live.json.
import { readFileSync, writeFileSync } from 'node:fs';
const TOKEN=readFileSync(process.env.HOME+'/Projects/secrets-manager/.env','utf8').split('\n').find(l=>l.startsWith('SHOPIFY_ADMIN_TOKEN=')).split('=')[1].trim();
const SHOP='https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json';
const DIR=new URL('.',import.meta.url).pathname;
const tgt=JSON.parse(readFileSync(DIR+'data/js882-target.json'));
const gql=(q)=>fetch(SHOP,{method:'POST',headers:{'X-Shopify-Access-Token':TOKEN,'Content-Type':'application/json'},body:JSON.stringify({query:q})}).then(r=>r.json());
const out=[]; let i=0;
for(const t of tgt){
const gid=`gid://shopify/Product/${t.product_id}`;
const q=`{p:product(id:"${gid}"){handle vendor status mfr:metafield(namespace:"custom",key:"manufacturer_sku"){value} variants(first:5){edges{node{title price}}}}}`;
try{
const r=await gql(q); const p=r.data&&r.data.p;
const sell=p?.variants.edges.map(e=>e.node).find(v=>!/sample/i.test(v.title));
out.push({...t, york_code:p?.mfr?.value||null, handle:p?.handle, status:p?.status, live_sell:sell?.price, live_uom:sell?.title});
}catch(e){ out.push({...t, york_code:null, err:String(e).slice(0,40)}); }
if(++i%100===0){ writeFileSync(DIR+'data/js882-live.json',JSON.stringify(out,null,1)); console.log('pulled',i); }
await new Promise(x=>setTimeout(x,120));
}
writeFileSync(DIR+'data/js882-live.json',JSON.stringify(out,null,1));
// cluster by York code prefix (book)
const book=c=>c?String(c).split('-')[0]:'(none)';
const clusters={}; for(const o of out){ const b=book(o.york_code); clusters[b]=(clusters[b]||0)+1; }
console.log('DONE',out.length,'| distinct York books:',Object.keys(clusters).length);
console.log('top books:',Object.entries(clusters).sort((a,b)=>b[1]-a[1]).slice(0,15).map(([k,v])=>`${k}:${v}`).join(' '));