← back to Dw Unbuyable Recovery Pilot

tk10978-scalamandre/rollback-all.mjs

28 lines

#!/usr/bin/env node
// Reverse the TK-10978 Scalamandre ADD-ROLL recovery: for each acted product,
// DELETE the added "Sold Per Roll" variant. The $4.25 Sample variant was never
// touched, so nothing else needs restoring. Reads data/prestate.jsonl.
// Usage: node rollback-all.mjs [--live]   default = dry-run (lists what it would delete).
import { readFileSync } from 'node:fs';
import { execSync } from 'child_process';
const LIVE = process.argv.includes('--live');
const T = execSync(`grep -E '^SHOPIFY_ADMIN_TOKEN=' ${process.env.HOME}/Projects/secrets-manager/.env|cut -d= -f2-`).toString().trim();
const DOMAIN = 'designer-laboratory-sandbox.myshopify.com', API = '2024-10';
const hdr = { 'X-Shopify-Access-Token': T, 'Content-Type': 'application/json' };
const REST = `https://${DOMAIN}/admin/api/${API}`;
const lines = readFileSync(new URL('./data/prestate.jsonl', import.meta.url).pathname, 'utf8').trim().split('\n').map(JSON.parse);
const sleep = ms => new Promise(r => setTimeout(r, ms));
async function api(path, opts) { const r = await fetch(`${REST}${path}`, { headers: hdr, ...opts }); return { status: r.status, json: await r.json().catch(() => ({})) }; }
let n = 0;
for (const l of lines) {
  const { json } = await api(`/products/${l.pid}.json`, {});
  const vs = json.product?.variants || [];
  // the added roll variant: sku==rollSku, option1='Sold Per Roll', not the sample id
  const added = vs.find(v => (v.sku || '').toLowerCase() === l.rollSku.toLowerCase() && v.id !== l.sampleVariantId);
  if (!added) { console.log('skip', l.pid, 'no added roll variant found (already reverted?)'); continue; }
  if (!LIVE) { console.log('WOULD DELETE', l.pid, 'variant', added.id, l.rollSku, '$' + added.price); continue; }
  await api(`/products/${l.pid}/variants/${added.id}.json`, { method: 'DELETE' });
  n++; console.log('deleted', l.pid, l.rollSku); await sleep(400);
}
console.log(LIVE ? `reverted ${n}` : 'dry-run complete');