← back to Petitionyour

scripts/refresh-legislators.js

49 lines

#!/usr/bin/env node
// Refresh the bundled public-domain congress member dataset.
//
// Source: unitedstates/congress-legislators (public domain). The repo's
// canonical source is YAML; the project publishes a generated JSON build to
// GitHub Pages, which is what we consume. We BUNDLE it under data/ so the app
// never depends on GitHub being reachable at runtime — re-run this script to
// pull fresh data after an election / appointment.
//
// Usage:  node scripts/refresh-legislators.js
// Cost:   $0 (single read-only external GET)
'use strict';

const fs = require('fs');
const path = require('path');

// Primary = GitHub Pages generated JSON. Fallback = raw main (currently YAML
// only, so this is really just a sanity net if Pages moves).
const SOURCES = [
  'https://unitedstates.github.io/congress-legislators/legislators-current.json',
  'https://raw.githubusercontent.com/unitedstates/congress-legislators/main/legislators-current.json',
];

const OUT = path.join(__dirname, '..', 'data', 'legislators-current.json');

async function main() {
  let lastErr;
  for (const url of SOURCES) {
    try {
      process.stdout.write(`Fetching ${url} ... `);
      const res = await fetch(url, { headers: { 'User-Agent': 'petitionyour-refresh' } });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const text = await res.text();
      const parsed = JSON.parse(text); // must be valid JSON, not YAML
      if (!Array.isArray(parsed) || !parsed.length) throw new Error('unexpected shape');
      fs.writeFileSync(OUT, JSON.stringify(parsed)); // compact — it's bundled data, not read by humans
      console.log(`ok (${parsed.length} members) -> ${OUT}`);
      return;
    } catch (err) {
      console.log(`failed: ${err.message}`);
      lastErr = err;
    }
  }
  console.error('All sources failed. Keeping existing bundled data.');
  process.exit(lastErr ? 1 : 0);
}

main();