/** * Mette in moto le cinque fonti di `src/lib/audit/sources/` su un URL. * * Le fonti sono in produzione dal 2026-08-19 ma INERTI: nessuna route le chiama. * Questo script e' l'unico modo di vederle funzionare, e serve a rispondere a una * domanda sola: **cosa e' stato misurato davvero, e cosa no.** Un buco qui e' il * risultato, non un errore da nascondere — il motore dovra' saperlo dire al cliente. * * Nessun LLM, nessun database, nessun browser headless (il VPS non lo regge). * * npx tsx scripts/audit-fonti.ts https://esempio.it * npx tsx scripts/audit-fonti.ts https://esempio.it --profilo=ecommerce * npx tsx scripts/audit-fonti.ts https://esempio.it --no-psi * * PAGESPEED_API_KEY (per PageSpeed e CrUX) viene letta dall'ambiente o da .env.local. */ import { readFileSync, writeFileSync, existsSync } from "node:fs"; import { resolve } from "node:path"; import { raccogliPagine } from "../src/lib/audit/sources/fetch"; import { rilevaCrux } from "../src/lib/audit/sources/crux"; import { rilevaPagespeedCompleto } from "../src/lib/audit/sources/pagespeed"; import { rilevaStorico } from "../src/lib/audit/sources/history"; import { rilevaSegnali } from "../src/lib/audit/sources/signals"; function caricaEnv() { if (process.env.PAGESPEED_API_KEY) return; const f = resolve(process.cwd(), ".env.local"); if (!existsSync(f)) return; for (const riga of readFileSync(f, "utf8").split("\n")) { const m = riga.match(/^\s*(?:export\s+)?([A-Z0-9_]+)\s*=\s*(.*)$/); if (m && !process.env[m[1]]) process.env[m[1]] = m[2].trim().replace(/^["']|["']$/g, ""); } } /** Esegue una fonte senza far cadere le altre: un buco e' un dato, non un crash. */ async function fonte(nome: string, f: () => Promise) { const t0 = Date.now(); try { const dati = await f(); return { nome, ok: true as const, ms: Date.now() - t0, dati }; } catch (e) { const msg = e instanceof Error ? e.message : String(e); return { nome, ok: false as const, ms: Date.now() - t0, errore: msg }; } } async function main() { caricaEnv(); const argv = process.argv.slice(2); const url = argv.find((a) => !a.startsWith("--")); if (!url) { console.error("uso: npx tsx scripts/audit-fonti.ts [--profilo=servizi] [--no-psi]"); process.exit(1); } const profilo = argv.find((a) => a.startsWith("--profilo="))?.split("=")[1] ?? "servizi"; const psi = !argv.includes("--no-psi"); const inizio = Date.now(); console.log(`\n ${url} · profilo ${profilo}${psi ? "" : " · PageSpeed saltato"}`); if (!process.env.PAGESPEED_API_KEY) { console.log(" ⚠ PAGESPEED_API_KEY assente: PageSpeed e CrUX risponderanno a vuoto."); } console.log(""); // La home serve alle altre due fonti: si scarica una volta sola. const raccolta = await fonte("pagine", () => raccogliPagine(url, profilo)); if (!raccolta.ok) { console.error(` ✗ pagine — ${raccolta.errore}\n\n Senza la home non parte nient'altro.`); process.exit(1); } const { home, homeHtml, homeHeaders, pagine, errori } = raccolta.dati; const risultati = [ raccolta, ...(await Promise.all([ fonte("crux", () => rilevaCrux(home)), ...(psi ? [fonte("pagespeed", () => rilevaPagespeedCompleto(home))] : []), fonte("storico", () => rilevaStorico(home, homeHtml)), fonte("segnali", () => rilevaSegnali(home, homeHtml, homeHeaders)), ])), ]; console.log(" FONTE ESITO TEMPO"); for (const r of risultati) { const esito = r.ok ? "ok " : "MUTA "; console.log(` ${r.nome.padEnd(11)} ${esito} ${(r.ms / 1000).toFixed(1)}s${r.ok ? "" : ` ${r.errore}`}`); } console.log(`\n Pagine raccolte: ${pagine.length} (${pagine.map((p) => p.ruolo).join(", ")})`); if (errori.length) console.log(` Non scaricate: ${errori.join(", ")}`); if (home !== url) console.log(` Canonico: ${home} (redirect dal valore passato)`); // Il grezzo e' il posto dove ogni numero del documento dovra' essere rintracciabile. const dominio = new URL(home).hostname.replace(/^www\./, ""); const file = resolve(process.cwd(), `audit-fonti-${dominio}.json`); writeFileSync(file, JSON.stringify({ url: home, profilo, quando: new Date().toISOString(), risultati }, null, 2)); console.log(`\n Grezzo: ${file}`); console.log(` Totale: ${((Date.now() - inizio) / 1000).toFixed(1)}s\n`); console.log(" Un numero entra in un documento solo se lo ritrovi qui dentro."); console.log(" Un punteggio PageSpeed va sempre con la sua data: ballano di 12 punti in mezz'ora.\n"); } main().catch((e) => { console.error("\nERRORE:", e instanceof Error ? e.message : e); process.exit(1); });