← back to Sanderson Onboard

scripts/rollback_sdg.mjs

31 lines

// rollback_sdg.mjs — reverse an SDG activation. Default: unpublish + set DRAFT (soft, reversible).
// --delete: hard delete the product. --pid=N single, or --all reads pilot/restore-map.jsonl.
import fs from 'node:fs';
const env = fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env', 'utf8');
const STORE = (env.match(/^SHOPIFY_STORE=(.+)$/m) || [])[1].trim();
const TOKEN = (env.match(/^SHOPIFY_FULL_ACCESS_TOKEN=(.+)$/m) || [])[1].trim(); // TK-10979 DTD-A: match forward path so undo has write scope (bridge; target=capability-scoped token)
const REST = `https://${STORE}/admin/api/2024-10`;
const H = { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' };
const DELETE = process.argv.includes('--delete');
const ALL = process.argv.includes('--all');
const PID = (process.argv.find(a => a.startsWith('--pid=')) || '').split('=')[1];
const sleep = ms => new Promise(r => setTimeout(r, ms));

async function one(pid) {
  if (DELETE) {
    const r = await fetch(`${REST}/products/${pid}.json`, { method: 'DELETE', headers: H });
    console.log(`  ${pid} DELETE ${r.status}`); return;
  }
  const r = await fetch(`${REST}/products/${pid}.json`, { method: 'PUT', headers: H, body: JSON.stringify({ product: { id: pid, status: 'draft', published: false } }) });
  console.log(`  ${pid} -> draft/unpublished ${r.status}`);
}
async function main() {
  let pids = [];
  if (PID) pids = [PID];
  else if (ALL) pids = fs.readFileSync(new URL('../pilot/restore-map.jsonl', import.meta.url).pathname, 'utf8').trim().split('\n').filter(Boolean).map(l => JSON.parse(l).pid);
  else { console.error('need --pid=N or --all'); process.exit(1); }
  console.log(`rollback ${pids.length} products (${DELETE ? 'DELETE' : 'draft+unpublish'})`);
  for (const p of pids) { await one(p); await sleep(300); }
}
main();