← back to Wolfgordon Crawl
add find-draft-candidates audit (8 WG rows fail width gate -> Needs-Width draft)
e2e3062708df0edf7699c0a8345ace39f246aad1 · 2026-06-19 16:08:32 -0700 · Steve
Files touched
A find-draft-candidates.js
Diff
commit e2e3062708df0edf7699c0a8345ace39f246aad1
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Jun 19 16:08:32 2026 -0700
add find-draft-candidates audit (8 WG rows fail width gate -> Needs-Width draft)
---
find-draft-candidates.js | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/find-draft-candidates.js b/find-draft-candidates.js
new file mode 100644
index 0000000..1e3dcb8
--- /dev/null
+++ b/find-draft-candidates.js
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+// Read-only: among the pushed cohort, find products that would FAIL the
+// activation gate after backfill (no image available AND/OR no width) — the
+// ones backfill-enrichment.js will set to DRAFT.
+const fs = require('fs'); const os = require('os');
+const { pool } = require('./scraper-utils');
+function loadToken() { const p = os.homedir() + '/Projects/secrets-manager/.env'; const line = fs.readFileSync(p, 'utf8').split('\n').find(l => l.startsWith('SHOPIFY_ADMIN_TOKEN=')); return line.slice('SHOPIFY_ADMIN_TOKEN='.length).replace(/^["']|["']$/g, '').trim(); }
+const TOKEN = loadToken(); const SHOP = 'designer-laboratory-sandbox.myshopify.com'; const GQL = `https://${SHOP}/admin/api/2024-10/graphql.json`;
+const wait = ms => new Promise(r => setTimeout(r, ms));
+async function gql(q, v) { await wait(250); const res = await fetch(GQL, { method: 'POST', headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' }, body: JSON.stringify({ query: q, variables: v }) }); const j = await res.json(); if (j.errors) throw new Error(JSON.stringify(j.errors)); return j.data; }
+function catImgs(row) { const i = []; if (row.image_url) i.push(row.image_url); try { const a = JSON.parse(row.all_images || '[]'); if (Array.isArray(a)) a.forEach(u => u && i.push(u)); } catch {} return i; }
+(async () => {
+ const rows = (await pool.query(`SELECT dw_sku, mfr_sku, pattern_name, color_name, width, width_inches, image_url, all_images, shopify_product_id FROM wolf_gordon_catalog WHERE shopify_product_id IS NOT NULL AND shopify_product_id<>''`)).rows;
+ const drafts = [];
+ for (let i = 0; i < rows.length; i += 50) {
+ const batch = rows.slice(i, i + 50);
+ const ids = batch.map(r => `"gid://shopify/Product/${r.shopify_product_id}"`).join(',');
+ const d = await gql(`{ nodes(ids:[${ids}]){ ... on Product { id status mediaCount{count} metafields(first:60){edges{node{namespace key}}} } } }`);
+ for (let k = 0; k < d.nodes.length; k++) {
+ const n = d.nodes[k], r = batch[k]; if (!n) continue;
+ const liveImg = n.mediaCount?.count || 0;
+ const have = new Set(n.metafields.edges.map(m => `${m.node.namespace}.${m.node.key}`));
+ const willHaveImg = liveImg > 0 || catImgs(r).length > 0;
+ const widthDisp = r.width || (r.width_inches ? `${r.width_inches}"` : null);
+ const willHaveWidth = have.has('global.width') || have.has('custom.width') || !!widthDisp;
+ if (!willHaveImg || !willHaveWidth) drafts.push({ dw_sku: r.dw_sku, mfr_sku: r.mfr_sku, pattern: r.pattern_name, color: r.color_name, status: n.status, liveImg, catImg: catImgs(r).length, willHaveImg, willHaveWidth });
+ }
+ process.stderr.write(`\r ${Math.min(i + 50, rows.length)}/${rows.length}`);
+ }
+ process.stderr.write('\n');
+ console.log('DRAFT candidates (fail gate):', drafts.length);
+ console.log(JSON.stringify(drafts, null, 2));
+ await pool.end();
+})().catch(e => { console.error('ERR', e.message); process.exit(1); });
← fe335e5 backfill: dedup images by basename (catalog cdn2-optimize vs
·
back to Wolfgordon Crawl
·
ROOT-CAUSE FIX: createProduct ships full desc+metafields fro 24bc927 →