← back to Greenland Onboard
scripts/shopify-cork-audit.mjs
47 lines
import { execSync } from 'node:child_process';
import { writeFileSync } from 'node:fs';
const TOKEN = execSync(`grep -E '^SHOPIFY_ADMIN_TOKEN=' ~/Projects/secrets-manager/.env | head -1 | cut -d= -f2-`, {encoding:'utf8'}).trim().replace(/^["']|["']$/g,'');
const STORE = 'designer-laboratory-sandbox.myshopify.com';
const API = `https://${STORE}/admin/api/2024-10/graphql.json`;
async function gql(query, variables={}) {
for (let i=0;i<6;i++){
const r = await fetch(API, { method:'POST', headers:{'X-Shopify-Access-Token':TOKEN,'Content-Type':'application/json'}, body: JSON.stringify({query,variables}) });
const j = await r.json();
if (j.errors) { if(JSON.stringify(j.errors).includes('Throttled')){await new Promise(s=>setTimeout(s,2500));continue;} throw new Error(JSON.stringify(j.errors)); }
return j.data;
}
}
const pubs = await gql(`{ publications(first:25){ nodes{ id name } } }`);
const onlineStore = pubs.publications.nodes.find(p=>/online store/i.test(p.name));
console.log('ONLINE_STORE_PUB', onlineStore?.id, onlineStore?.name);
let after=null, all=[];
do {
const d = await gql(`query($after:String){ products(first:100, query:"sku:Cork-*", after:$after){ pageInfo{hasNextPage endCursor} nodes{
id title status vendor handle
publishedOnPublication(publicationId:"${onlineStore.id}")
variants(first:10){ nodes{ sku price } }
} } }`, {after});
const conn = d.products;
all.push(...conn.nodes);
after = conn.pageInfo.hasNextPage ? conn.pageInfo.endCursor : null;
} while(after);
const cork = all.filter(p => p.variants.nodes.some(v => /^Cork-\d/.test(v.sku||'')));
const rows = cork.map(p => {
const corkSku = (p.variants.nodes.find(v=>/^Cork-\d/.test(v.sku||''))||{}).sku;
const yardV = p.variants.nodes.find(v=>/^Cork-\d+$/.test(v.sku||''));
return { id:p.id, title:p.title, status:p.status, vendor:p.vendor, handle:p.handle,
onlinePublished: p.publishedOnPublication, sku:corkSku,
yardPrice: yardV?.price, skus:p.variants.nodes.map(v=>v.sku) };
});
writeFileSync('/tmp/gl_shopify_state.json', JSON.stringify({onlineStorePub:onlineStore.id, rows}, null, 2));
const byStatus = {};
for (const r of rows){ const k=r.status+(r.onlinePublished?'/online':'/offline'); byStatus[k]=(byStatus[k]||0)+1; }
console.log('TOTAL cork products:', rows.length);
console.log('breakdown status/online:', JSON.stringify(byStatus,null,2));
console.log('vendors:', JSON.stringify([...new Set(rows.map(r=>r.vendor))]));
const leaks = rows.filter(r => /greenland/i.test(r.title) || /greenland/i.test(r.vendor||''));
console.log('GREENLAND LEAKS:', leaks.length, JSON.stringify(leaks.map(l=>l.sku)));