← back to Interiordesignershowroom

scripts/ingest.js

55 lines

// Runs every enabled adapter, normalizes results, and UPSERTs into products.
// Safe to run repeatedly (cron): the (network, external_id) key means re-ingest
// updates prices/stock in place instead of duplicating.
//
// Usage:  node scripts/ingest.js [--limit=500] [--only=cj,amazon]
// Env is read from the process (pm2 ecosystem / shell). dotenv is optional:
try { require('dotenv').config(); } catch (_) { /* dotenv not installed — env comes from the shell */ }
const db = require('../lib/db');
const adapters = require('../lib/adapters');
const { normalizeProduct, UPSERT_SQL, upsertParams } = require('../lib/normalize');

function arg(name, def) {
  const hit = process.argv.find((a) => a.startsWith(`--${name}=`));
  return hit ? hit.split('=')[1] : def;
}

async function main() {
  const env = process.env;
  const limit = parseInt(arg('limit', '500'), 10);
  const only = (arg('only', '') || '').split(',').filter(Boolean);

  await db.query('SELECT 1');
  const summary = [];

  for (const a of adapters) {
    if (only.length && !only.includes(a.network)) continue;
    if (!a.enabled(env)) { summary.push(`${a.network}: skipped (no creds)`); continue; }

    let raws = [];
    try {
      raws = await a.fetch(env, { limit });
    } catch (e) {
      summary.push(`${a.network}: ERROR ${e.message}`);
      continue;
    }

    let ok = 0, skip = 0;
    for (const raw of raws) {
      const norm = normalizeProduct(raw, a.network);
      if (!norm) { skip++; continue; }
      try {
        await db.query(UPSERT_SQL, upsertParams(norm));
        ok++;
      } catch (e) { skip++; }
    }
    summary.push(`${a.network}: ${ok} upserted, ${skip} skipped (of ${raws.length})`);
  }

  console.log('--- ingest summary ---');
  summary.forEach((s) => console.log('  ' + s));
  await db.pool.end();
}

main().catch((e) => { console.error(e); process.exit(1); });