← back to Homesonspec

apps/workers/src/cli.ts

126 lines

import { prisma } from "@homesonspec/database";
import { meridianHomesAdapter } from "@homesonspec/collector-meridian-homes";
import { tollBrothersAdapter } from "@homesonspec/collector-toll-brothers";
import { lennarAdapter } from "@homesonspec/collector-lennar";
import { drHortonAdapter } from "@homesonspec/collector-dr-horton";
import { kbHomeAdapter } from "@homesonspec/collector-kb-home";
import { pulteAdapter } from "@homesonspec/collector-pulte";
import { triPointeAdapter } from "@homesonspec/collector-tri-pointe";
import { taylorMorrisonAdapter } from "@homesonspec/collector-taylor-morrison";
import { discoveryAdapter } from "@homesonspec/collector-discovery";
import { davidWeekleyAdapter } from "@homesonspec/collector-david-weekley";
import { ashtonWoodsAdapter } from "@homesonspec/collector-ashton-woods";
import { dreamFindersAdapter } from "@homesonspec/collector-dream-finders";
import { meritageHomesAdapter } from "@homesonspec/collector-meritage-homes";
import { landseaAdapter } from "@homesonspec/collector-landsea-homes";
import { ryanHomesAdapter } from "@homesonspec/collector-ryan-homes";
import { highlandHomesAdapter } from "@homesonspec/collector-highland-homes";
import { highlandHomesFlAdapter } from "@homesonspec/collector-highland-homes-fl";
import { lgiHomesAdapter } from "@homesonspec/collector-lgi-homes";
import { sheaHomesAdapter } from "@homesonspec/collector-shea-homes";
import { centuryAdapter } from "@homesonspec/collector-century-communities";
import { beazerAdapter } from "@homesonspec/collector-beazer";
import { dreesHomesAdapter } from "@homesonspec/collector-drees-homes";
import { perryHomesAdapter } from "@homesonspec/collector-perry-homes";
import { brookfieldAdapter } from "@homesonspec/collector-brookfield";
import { holtHomesAdapter } from "@homesonspec/collector-holt-homes";
import { fischerHomesAdapter } from "@homesonspec/collector-fischer-homes";
import { fultonHomesAdapter } from "@homesonspec/collector-fulton-homes";
import { glHomesAdapter } from "@homesonspec/collector-gl-homes";
import { mattamyAdapter } from "@homesonspec/collector-mattamy";
import { khovnanianAdapter } from "@homesonspec/collector-khovnanian";
import { miHomesAdapter } from "@homesonspec/collector-mi-homes";
import { smithDouglasAdapter } from "@homesonspec/collector-smith-douglas";
import { goodallHomesAdapter } from "@homesonspec/collector-goodall-homes";
import { brohnHomesAdapter } from "@homesonspec/collector-brohn-homes";
import { oakwoodHomesAdapter } from "@homesonspec/collector-oakwood-homes";
import { summitHomesKcAdapter } from "@homesonspec/collector-summit-homes-kc";
import { mungoHomesAdapter } from "@homesonspec/collector-mungo-homes";
import { chafinCommunitiesAdapter } from "@homesonspec/collector-chafin-communities";
import { harrisDoyleAdapter } from "@homesonspec/collector-harris-doyle";
import { legacyAlAdapter } from "@homesonspec/collector-legacy-al";
import { arborAdapter } from "@homesonspec/collector-arbor";
import { silverthorneAdapter } from "@homesonspec/collector-silverthorne";
import { eliteHomesAdapter } from "@homesonspec/collector-elite-homes";
import { berkeleyBuildingAdapter } from "@homesonspec/collector-berkeley-building";
import { runPipeline } from "./pipeline";
import { recordSourceRun } from "./verify";

/**
 * Direct pipeline runner — no queue required.
 *   pnpm --filter @homesonspec/workers pipeline -- --adapter=meridian-homes-fixtures
 */
const ADAPTERS = {
  [meridianHomesAdapter.key]: meridianHomesAdapter,
  [tollBrothersAdapter.key]: tollBrothersAdapter,
  [lennarAdapter.key]: lennarAdapter,
  [drHortonAdapter.key]: drHortonAdapter,
  [kbHomeAdapter.key]: kbHomeAdapter,
  [pulteAdapter.key]: pulteAdapter,
  [triPointeAdapter.key]: triPointeAdapter,
  [taylorMorrisonAdapter.key]: taylorMorrisonAdapter,
  [discoveryAdapter.key]: discoveryAdapter,
  [davidWeekleyAdapter.key]: davidWeekleyAdapter,
  [ashtonWoodsAdapter.key]: ashtonWoodsAdapter,
  [dreamFindersAdapter.key]: dreamFindersAdapter,
  [meritageHomesAdapter.key]: meritageHomesAdapter,
  [landseaAdapter.key]: landseaAdapter,
  [ryanHomesAdapter.key]: ryanHomesAdapter,
  [highlandHomesAdapter.key]: highlandHomesAdapter,
  [highlandHomesFlAdapter.key]: highlandHomesFlAdapter,
  [lgiHomesAdapter.key]: lgiHomesAdapter,
  [sheaHomesAdapter.key]: sheaHomesAdapter,
  [centuryAdapter.key]: centuryAdapter,
  [beazerAdapter.key]: beazerAdapter,
  [dreesHomesAdapter.key]: dreesHomesAdapter,
  [perryHomesAdapter.key]: perryHomesAdapter,
  [brookfieldAdapter.key]: brookfieldAdapter,
  [holtHomesAdapter.key]: holtHomesAdapter,
  [fischerHomesAdapter.key]: fischerHomesAdapter,
  [fultonHomesAdapter.key]: fultonHomesAdapter,
  [glHomesAdapter.key]: glHomesAdapter,
  [mattamyAdapter.key]: mattamyAdapter,
  [khovnanianAdapter.key]: khovnanianAdapter,
  [miHomesAdapter.key]: miHomesAdapter,
  [smithDouglasAdapter.key]: smithDouglasAdapter,
  [goodallHomesAdapter.key]: goodallHomesAdapter,
  [brohnHomesAdapter.key]: brohnHomesAdapter,
  [oakwoodHomesAdapter.key]: oakwoodHomesAdapter,
  [summitHomesKcAdapter.key]: summitHomesKcAdapter,
  [mungoHomesAdapter.key]: mungoHomesAdapter,
  [chafinCommunitiesAdapter.key]: chafinCommunitiesAdapter,
  [harrisDoyleAdapter.key]: harrisDoyleAdapter,
  [legacyAlAdapter.key]: legacyAlAdapter,
  [arborAdapter.key]: arborAdapter,
  [silverthorneAdapter.key]: silverthorneAdapter,
  [eliteHomesAdapter.key]: eliteHomesAdapter,
  [berkeleyBuildingAdapter.key]: berkeleyBuildingAdapter,
};

async function main() {
  const arg = process.argv.find((a) => a.startsWith("--adapter="));
  const key = arg?.split("=")[1] ?? meridianHomesAdapter.key;
  const adapter = ADAPTERS[key];
  if (!adapter) {
    console.error(`Unknown adapter "${key}". Known: ${Object.keys(ADAPTERS).join(", ")}`);
    process.exit(1);
  }
  console.log(`Running pipeline for ${key} (extractor v${adapter.version})…`);
  try {
    const summary = await runPipeline(adapter);
    console.log(JSON.stringify(summary, null, 2));
  } catch (err) {
    // Record the failure so the failure streak advances toward auto-pause.
    const message = err instanceof Error ? err.message : String(err);
    await recordSourceRun(key, { ok: false, kind: "pipeline", message }).catch(() => {});
    throw err;
  }
}

main()
  .catch((error) => {
    console.error(error);
    process.exitCode = 1;
  })
  .finally(() => prisma.$disconnect());