scripts/seed.ts
Rama main · réplica de lectura del repositorio original.
// Seeds a fresh site from the industry pack: the demo sources (industry/sources.json, only the ones not
// there yet, so admin edits are never undone). Topics need no seeding: they are read from industry/topics.json.
// Re-runnable: node --env-file=.env scripts/seed.ts
import { readFileSync } from "node:fs";
import path from "node:path";
import { REPO_ROOT } from "@aihot/backend/config";
import { closeDb, sql } from "@aihot/backend/db";
import { assertSupportedConfig } from "@aihot/backend/sources/config-keys";
interface SeedSource {
id: string;
name: string;
kind: "rss" | "web_list" | "json_list" | "x_search" | "mp_account" | "external";
config: Record<string, unknown>;
tier?: string;
owner_entity_id?: string | null;
participation_mode?: string;
interval_minutes?: number;
tags?: string[];
site_fulltext?: boolean;
syndicate_fulltext?: boolean;
enabled?: boolean;
}
const { sources } = JSON.parse(readFileSync(path.join(REPO_ROOT, "industry/sources.json"), "utf8")) as { sources: SeedSource[] };
let added = 0;
for (const s of sources) {
assertSupportedConfig(s.kind, s.config);
const tier = s.tier ?? "T2";
// First-party means a T1 source, as the admin sets it.
const inserted = await sql`
INSERT INTO sources (id, name, kind, config, tier, first_party, owner_entity_id, participation_mode, interval_minutes, tags, site_fulltext, syndicate_fulltext, enabled, next_fetch_at)
VALUES (${s.id}, ${s.name}, ${s.kind}, ${sql.json(s.config as never)}, ${tier}, ${tier === "T1"}, ${s.owner_entity_id ?? null},
${s.participation_mode ?? "editorial"}, ${s.interval_minutes ?? 60}, ${s.tags ?? []}, ${s.site_fulltext ?? false}, ${s.syndicate_fulltext ?? false},
${s.enabled ?? true}, now())
ON CONFLICT (id) DO NOTHING RETURNING id`;
added += inserted.length;
}
console.log(`sources: ${added} added, ${sources.length - added} already there`);
await closeDb();