← back to Rebel Walls Push
scripts/TK-10405-aprime-undo.mjs
40 lines
#!/usr/bin/env node
// UNDO for TK-10405 A' mitigation — restores each held orphan's original SKU (strips -DUP)
// and restores its inventory available to qty_before, from the recorded restore map.
// Run: node scripts/TK-10405-aprime-undo.mjs
import fs from 'node:fs';
const DOM = 'designer-laboratory-sandbox.myshopify.com';
const VER = '2024-10';
const RESTORE = new URL('../data/TK-10405-restore-map.json', import.meta.url).pathname;
const env = fs.readFileSync(process.env.HOME + '/Projects/secrets-manager/.env', 'utf8');
const TOKEN = (env.match(/^SHOPIFY_FULL_ACCESS_TOKEN=(.+)$/m)?.[1] || '').trim().replace(/^["']|["']$/g, '');
async function gql(query, variables, tries = 6) {
for (let i = 0; i < tries; i++) {
const r = await fetch(`https://${DOM}/admin/api/${VER}/graphql.json`, {
method: 'POST', headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables }) });
if ([429, 500, 502, 503].includes(r.status) && i < tries - 1) { await new Promise(s => setTimeout(s, 1500 * (i + 1))); continue; }
return r.json();
}
}
const M_SKU = `mutation($productId:ID!,$variants:[ProductVariantsBulkInput!]!){
productVariantsBulkUpdate(productId:$productId,variants:$variants){ productVariants{ id sku } userErrors{ field message } } }`;
const M_INV = `mutation($input:InventorySetQuantitiesInput!){
inventorySetQuantities(input:$input){ inventoryAdjustmentGroup{ createdAt } userErrors{ field message } } }`;
(async () => {
const rm = JSON.parse(fs.readFileSync(RESTORE, 'utf8'));
const ps = rm.a_prime_mitigation?.prestate;
if (!ps) { console.error('no a_prime_mitigation.prestate in restore map — nothing to undo'); process.exit(1); }
for (const [id, e] of Object.entries(ps)) {
console.log(`Undo ${e.label} (${id}): sku -> ${e.sku_before}, qty -> ${e.qty_before}`);
const rs = await gql(M_SKU, { productId: e.product_gid, variants: [{ id: e.variant_gid, inventoryItem: { sku: e.sku_before } }] });
console.log(' sku userErrors:', JSON.stringify(rs?.data?.productVariantsBulkUpdate?.userErrors || rs?.errors || []));
const ri = await gql(M_INV, { input: { name: 'available', reason: 'correction', ignoreCompareQuantity: true,
quantities: [{ inventoryItemId: e.inventory_item_gid, locationId: e.location_gid, quantity: e.qty_before }] } });
console.log(' inv userErrors:', JSON.stringify(ri?.data?.inventorySetQuantities?.userErrors || ri?.errors || []));
}
console.log('UNDO complete.');
})();