← back to Dw Five Field Step0

scripts/test-50-variants.js

112 lines

const { Pool } = require('pg');
const fs = require('fs');
const path = require('path');

const env = fs.readFileSync(path.join(process.env.HOME, '/Projects/secrets-manager/.env'), 'utf8');
const TOKEN = (env.match(/SHOPIFY_ADMIN_TOKEN=(\S+)/) || [])[1];
const DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
const VER = '2024-10';

delete process.env.PGPASSWORD;
delete process.env.DATABASE_URL;
const pool = new Pool({ host: '/tmp', database: 'dw_unified' });

const SAMPLE_PRICE = '4.25';

async function createVariantRest(productId, sku, title, price) {
  for (let attempt = 0; attempt < 5; attempt++) {
    const r = await fetch(
      `https://${DOMAIN}/admin/api/${VER}/products/${productId}/variants.json`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Shopify-Access-Token': TOKEN
        },
        body: JSON.stringify({
          variant: {
            title, sku, price,
            option1: 'Sample'  // Unique option value for sample variants
          }
        })
      }
    );
    const j = await r.json();

    if (r.status === 429) {
      const waitMs = 3000 * (attempt + 1);
      console.log(`    [THROTTLED] Retry ${attempt + 1}/5 in ${waitMs}ms...`);
      await new Promise(s => setTimeout(s, waitMs));
      continue;
    }

    if (r.status === 422) {
      const errorMsg = JSON.stringify(j.errors);
      if (errorMsg.includes('has already been taken') || errorMsg.includes("already exists")) {
        return { success: true, skipped: true };
      }
      throw new Error(errorMsg);
    }

    if (!r.ok || j.errors) {
      throw new Error(j.errors ? JSON.stringify(j.errors) : `HTTP ${r.status}`);
    }

    return { success: true, variant: j.variant };
  }
  throw new Error('Rate limited (5 attempts exhausted)');
}

(async () => {
  console.log('[TEST] Creating 50 sample variants...\n');
  
  const res = await pool.query(`
    SELECT DISTINCT
      af.shopify_id, af.dw_sku
    FROM active_five_field_gaps af
    WHERE af.vendor = 'Clarke And Clarke'
      AND af.fix_type = 'add-sample'
      AND af.priceable = true
    ORDER BY af.dw_sku
    LIMIT 50
  `);

  let created = 0, errors = 0, skipped = 0;
  const startTime = Date.now();

  for (let i = 0; i < res.rows.length; i++) {
    const sku = res.rows[i];
    const productId = sku.shopify_id.match(/\d+$/)[0];

    try {
      const result = await createVariantRest(
        productId,
        `${sku.dw_sku}-Sample-50TEST-V3`,
        'Sample',
        SAMPLE_PRICE
      );

      if (result.skipped) {
        skipped++;
        if ((i + 1) % 10 === 0) console.log(`  ${i + 1}/50: ${sku.dw_sku} (skipped)`);
      } else {
        created++;
        if ((i + 1) % 10 === 0) console.log(`  ${i + 1}/50: ${sku.dw_sku} (created)`);
      }
    } catch (e) {
      errors++;
      console.log(`  ❌ ${i + 1}/50: ${sku.dw_sku}: ${e.message.slice(0, 60)}`);
    }

    if ((i + 1) % 10 === 0) {
      await new Promise(s => setTimeout(s, 1000));
    }
  }

  const elapsed = ((Date.now() - startTime) / 1000 / 60).toFixed(2);
  console.log(`\n[RESULT] ${created} created, ${skipped} skipped, ${errors} errors in ${elapsed} min`);
  console.log(`  Estimated rate: ~${(res.rows.length / elapsed).toFixed(0)} variants/min\n`);

  process.exit(errors > 0 ? 1 : 0);
})().finally(() => pool.end());