← back to Dw Add Sellable Variant Tk10902

tk10825-rollback.mjs

35 lines

#!/usr/bin/env node
// TK-10825 ROLLBACK — re-publish every product this ticket unpublished, from the ledger record.
// Reads tk10825-run-log.jsonl for action=='unpublished' rows and PUTs published=true back.
// Usage: node tk10825-rollback.mjs [--live]   (default DRY-RUN)

import fs from 'fs';
import { execSync } from 'child_process';

const DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
const API = '2024-10';
const TOKEN = execSync(`grep -E '^SHOPIFY_ADMIN_TOKEN=' ${process.env.HOME}/Projects/secrets-manager/.env | cut -d= -f2-`).toString().trim();
const LIVE = process.argv.includes('--live');
const RUNLOG = `${process.cwd()}/tk10825-run-log.jsonl`;
const base = `https://${DOMAIN}/admin/api/${API}`;
const hdr = { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' };
const sleep = ms => new Promise(r => setTimeout(r, ms));

const rows = fs.readFileSync(RUNLOG, 'utf8').split('\n').filter(Boolean)
  .map(JSON.parse).filter(r => r.action === 'unpublished');
console.log(`\n=== ${LIVE ? 'LIVE RE-PUBLISH' : 'DRY-RUN'} — ${rows.length} products to restore ===\n`);

let done = 0;
for (const r of rows) {
  if (!LIVE) { console.log(`WOULD RE-PUBLISH ${r.pid} "${r.title}"`); done++; continue; }
  for (let a = 0; a < 5; a++) {
    const res = await fetch(`${base}/products/${r.pid}.json`, { method: 'PUT', headers: hdr, body: JSON.stringify({ product: { id: Number(r.pid), published: true } }) });
    if (res.status === 429) { await sleep(2500); continue; }
    console.log(`${res.status === 200 ? 'RE-PUBLISHED' : 'FAILED_' + res.status} ${r.pid} "${r.title}"`);
    if (res.status === 200) done++;
    break;
  }
  await sleep(600);
}
console.log(`\n=== DONE: restored=${done}/${rows.length} ===`);