all repos — red-anatomia @ main

red-anatomia

src/collectors/lighthouse.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
import type { Observations, Lighthouse } from '../core/types.js';

export async function coletarLighthouse(obs: Observations): Promise<void> {
  try {
    const { launch } = await import('chrome-launcher');
    const lighthouseMod = await import('lighthouse');
    const lighthouse = (lighthouseMod.default ?? lighthouseMod) as unknown as (
      url: string,
      flags: Record<string, unknown>,
      config?: unknown,
    ) => Promise<{ lhr: { categories: Record<string, { score: number | null }> } }>;

    const { chromium } = await import('playwright');
    const chromePath = chromium.executablePath();

    const chrome = await launch({
      chromePath,
      chromeFlags: ['--headless=new', '--no-sandbox', '--disable-gpu'],
    });

    try {
      const resultado = await lighthouse(obs.urlFinal || obs.urlSolicitada, {
        port: chrome.port,
        output: 'json',
        logLevel: 'silent',
        onlyCategories: ['performance', 'accessibility', 'seo', 'best-practices'],
      });

      const cats = resultado.lhr.categories;
      const nota = (chave: string): number | undefined => {
        const s = cats[chave]?.score;
        return s == null ? undefined : Math.round(s * 100);
      };

      const lh: Lighthouse = {
        performance: nota('performance'),
        acessibilidade: nota('accessibility'),
        seo: nota('seo'),
        boasPraticas: nota('best-practices'),
      };
      obs.lighthouse = lh;
    } finally {
      await chrome.kill();
    }
  } catch (erro) {
    obs.avisos.push(`Auditoria Lighthouse indisponível: ${(erro as Error).message}`);
  }
}