← back to Dw Unbuyable Recovery Pilot
tk11252-hollywood/set-status-8.mjs
53 lines
#!/usr/bin/env node
// TK-11252 fork-1 — set the 8 genuine dead-ends to DRAFT (Steve-approved Option B, 2026-09-14),
// with a clean re-activate undo. Reads the prestate snapshot for the exact 8 GIDs.
// node set-status-8.mjs --draft <prestate.json> # set the 8 -> DRAFT (verifies each)
// node set-status-8.mjs --activate <prestate.json> # UNDO: set them back -> ACTIVE
import { readFileSync } from 'node:fs';
const TOKEN = readFileSync('/Users/macstudio3/Projects/secrets-manager/.env','utf8')
.split('\n').find(l=>l.startsWith('SHOPIFY_ADMIN_TOKEN=')).split('=').slice(1).join('=').trim();
const SHOP='designer-laboratory-sandbox.myshopify.com', API='2024-10';
const mode = process.argv[2];
const snapPath = process.argv[3];
if (!['--draft','--activate'].includes(mode) || !snapPath){
console.error('usage: node set-status-8.mjs --draft|--activate <prestate.json>');
process.exit(2);
}
const TARGET_STATUS = mode==='--draft' ? 'DRAFT' : 'ACTIVE';
const snap = JSON.parse(readFileSync(snapPath,'utf8'));
const products = snap.products;
if (mode==='--draft'){
// hard guard: only proceed if every product was ACTIVE in prestate (matches Steve's approval scope)
const bad = products.filter(p=>p.prior_status!=='ACTIVE');
if (bad.length){ console.error('ABORT: prestate has non-ACTIVE rows', bad.map(b=>b.sku)); process.exit(3); }
}
async function gql(query, variables){
const r = await fetch(`https://${SHOP}/admin/api/${API}/graphql.json`, {
method:'POST', headers:{'Content-Type':'application/json','X-Shopify-Access-Token':TOKEN},
body: JSON.stringify({ query, variables }) });
const j = await r.json();
if (j.errors) throw new Error('GraphQL: '+JSON.stringify(j.errors));
return j.data;
}
const M = `mutation($input:ProductInput!){
productUpdate(input:$input){ product{ id status } userErrors{ field message } } }`;
const READ = `query($id:ID!){ product(id:$id){ id status } }`;
let ok=0, fail=0;
for (const p of products){
const res = await gql(M, { input:{ id:p.gid, status:TARGET_STATUS } });
const ue = res.productUpdate.userErrors;
if (ue && ue.length){ console.log(`FAIL ${p.sku}: ${JSON.stringify(ue)}`); fail++; continue; }
// verify by independent re-read
const chk = await gql(READ, { id:p.gid });
const got = chk.product.status;
const good = got===TARGET_STATUS;
console.log(`${good?'OK ':'FAIL'} ${p.sku.padEnd(14)} ${p.gid.split('/').pop()} -> ${got}${good?'':' (EXPECTED '+TARGET_STATUS+')'}`);
good ? ok++ : fail++;
await new Promise(r=>setTimeout(r,300));
}
console.log(`\n${mode} complete: ${ok}/${products.length} verified ${TARGET_STATUS}, ${fail} fail`);
process.exit(fail?1:0);