{"version":3,"sources":["../../src/pagespeed/constants.ts","../../src/pagespeed/extractors.ts","../../src/pagespeed/utils.ts","../../src/pagespeed/insights.ts","../../src/pagespeed/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @silverassist/performance-toolkit\n *\n * PageSpeed API constants and configuration values.\n *\n * @module pagespeed/constants\n * @author Miguel Colmenares <me@miguelcolmenares.com>\n * @license PolyForm-Noncommercial-1.0.0\n */\n\nimport type { Category } from \"../types\";\n\n/** PageSpeed Insights API base URL */\nexport const PSI_API_URL =\n  \"https://www.googleapis.com/pagespeedonline/v5/runPagespeed\";\n\n/** Default request timeout in milliseconds */\nexport const DEFAULT_TIMEOUT = 60000;\n\n/** Default categories to analyze */\nexport const DEFAULT_CATEGORIES: Category[] = [\n  \"performance\",\n  \"accessibility\",\n  \"best-practices\",\n  \"seo\",\n];\n\n/** Audit IDs for performance improvement opportunities */\nexport const OPPORTUNITY_AUDITS = [\n  \"render-blocking-resources\",\n  \"unused-css-rules\",\n  \"unused-javascript\",\n  \"modern-image-formats\",\n  \"offscreen-images\",\n  \"unminified-css\",\n  \"unminified-javascript\",\n  \"efficient-animated-content\",\n  \"uses-optimized-images\",\n  \"uses-responsive-images\",\n  \"server-response-time\",\n  \"uses-text-compression\",\n  \"uses-rel-preconnect\",\n  \"uses-rel-preload\",\n  \"font-display\",\n  \"third-party-summary\",\n] as const;\n\n/** Audit IDs for diagnostic information */\nexport const DIAGNOSTIC_AUDITS = [\n  \"mainthread-work-breakdown\",\n  \"bootup-time\",\n  \"dom-size\",\n  \"critical-request-chains\",\n  \"network-requests\",\n  \"network-rtt\",\n  \"network-server-latency\",\n  \"long-tasks\",\n  \"non-composited-animations\",\n  \"unsized-images\",\n  \"viewport\",\n  \"no-document-write\",\n  \"js-libraries\",\n] as const;\n\n/** Third-party entity name patterns */\nexport const THIRD_PARTY_PATTERNS: Record<string, string> = {\n  facebook: \"Facebook\",\n  \"fb.com\": \"Facebook\",\n  fbcdn: \"Facebook\",\n  google: \"Google\",\n  googleapis: \"Google APIs\",\n  gstatic: \"Google Static\",\n  googletagmanager: \"Google Tag Manager\",\n  \"google-analytics\": \"Google Analytics\",\n  doubleclick: \"DoubleClick\",\n  twitter: \"Twitter\",\n  twimg: \"Twitter\",\n  linkedin: \"LinkedIn\",\n  trustedform: \"TrustedForm\",\n  leadid: \"LeadID\",\n  jornaya: \"Jornaya\",\n  cloudflare: \"Cloudflare\",\n  cloudfront: \"CloudFront\",\n  amazonaws: \"AWS\",\n  cdn: \"CDN\",\n  jquery: \"jQuery\",\n  unpkg: \"unpkg\",\n  cdnjs: \"cdnjs\",\n  bootstrapcdn: \"Bootstrap CDN\",\n};\n","/**\n * @silverassist/performance-toolkit\n *\n * PageSpeed data extractors for scores, metrics, opportunities, and diagnostics.\n *\n * @module pagespeed/extractors\n * @author Miguel Colmenares <me@miguelcolmenares.com>\n * @license PolyForm-Noncommercial-1.0.0\n */\n\nimport type {\n  CoreWebVitals,\n  CategoryScores,\n  Diagnostic,\n  LCPElement,\n  MetricValue,\n  Opportunity,\n  PageSpeedResponse,\n} from \"../types\";\nimport { OPPORTUNITY_AUDITS, DIAGNOSTIC_AUDITS } from \"./constants\";\n\ntype LighthouseResult = PageSpeedResponse[\"lighthouseResult\"];\ntype LighthouseAudit = LighthouseResult[\"audits\"][string];\n\n/**\n * Extracts category scores from Lighthouse result\n */\nexport function extractScores(result: LighthouseResult): CategoryScores {\n  const { categories } = result;\n\n  return {\n    performance:\n      categories.performance?.score != null\n        ? Math.round(categories.performance.score * 100)\n        : null,\n    accessibility:\n      categories.accessibility?.score != null\n        ? Math.round(categories.accessibility.score * 100)\n        : null,\n    bestPractices:\n      categories[\"best-practices\"]?.score != null\n        ? Math.round(categories[\"best-practices\"].score * 100)\n        : null,\n    seo:\n      categories.seo?.score != null\n        ? Math.round(categories.seo.score * 100)\n        : null,\n  };\n}\n\n/**\n * Extracts Core Web Vitals metrics from audits\n */\nexport function extractMetrics(result: LighthouseResult): CoreWebVitals {\n  const { audits } = result;\n\n  return {\n    lcp: extractMetricValue(audits[\"largest-contentful-paint\"]),\n    fcp: extractMetricValue(audits[\"first-contentful-paint\"]),\n    cls: extractMetricValue(audits[\"cumulative-layout-shift\"]),\n    tbt: extractMetricValue(audits[\"total-blocking-time\"]),\n    si: extractMetricValue(audits[\"speed-index\"]),\n    tti: extractMetricValue(audits[\"interactive\"]),\n  };\n}\n\n/**\n * Extracts a single metric value from audit\n */\nexport function extractMetricValue(audit?: LighthouseAudit): MetricValue {\n  if (!audit) {\n    return { value: 0, displayValue: \"N/A\", rating: \"poor\" };\n  }\n\n  const value = audit.numericValue ?? 0;\n  const displayValue = audit.displayValue ?? \"N/A\";\n  const score = audit.score ?? 0;\n\n  let rating: MetricValue[\"rating\"];\n  if (score >= 0.9) {\n    rating = \"good\";\n  } else if (score >= 0.5) {\n    rating = \"needs-improvement\";\n  } else {\n    rating = \"poor\";\n  }\n\n  return { value, displayValue, rating };\n}\n\n/**\n * Extracts LCP element information\n */\nexport function extractLCPElement(\n  result: LighthouseResult,\n): LCPElement | undefined {\n  const lcpAudit = result.audits[\"largest-contentful-paint-element\"];\n\n  if (!lcpAudit?.details?.items?.[0]) {\n    return undefined;\n  }\n\n  const item = lcpAudit.details.items[0] as Record<string, unknown>;\n  const node = item.node as Record<string, unknown> | undefined;\n\n  return {\n    tagName: (node?.nodeLabel as string) ?? \"Unknown\",\n    selector: (node?.selector as string) ?? \"\",\n    url: node?.lhId as string | undefined,\n    nodePath: (node?.path as string) ?? \"\",\n    snippet: (node?.snippet as string) ?? undefined,\n  };\n}\n\n/**\n * Extracts performance improvement opportunities\n */\nexport function extractOpportunities(result: LighthouseResult): Opportunity[] {\n  const opportunities: Opportunity[] = [];\n\n  for (const id of OPPORTUNITY_AUDITS) {\n    const audit = result.audits[id];\n    if (\n      !audit ||\n      audit.score === 1 ||\n      audit.scoreDisplayMode === \"notApplicable\"\n    ) {\n      continue;\n    }\n\n    opportunities.push({\n      id,\n      title: audit.title,\n      description: audit.description,\n      savingsMs: audit.details?.overallSavingsMs,\n      savingsBytes: audit.details?.overallSavingsBytes,\n      score: audit.score,\n      items: audit.details?.items as Array<Record<string, unknown>> | undefined,\n    });\n  }\n\n  return opportunities.sort((a, b) => (b.savingsMs ?? 0) - (a.savingsMs ?? 0));\n}\n\n/**\n * Extracts diagnostic information\n */\nexport function extractDiagnostics(result: LighthouseResult): Diagnostic[] {\n  const diagnostics: Diagnostic[] = [];\n\n  for (const id of DIAGNOSTIC_AUDITS) {\n    const audit = result.audits[id];\n    if (!audit || audit.scoreDisplayMode === \"notApplicable\") {\n      continue;\n    }\n\n    diagnostics.push({\n      id,\n      title: audit.title,\n      description: audit.description,\n      displayValue: audit.displayValue,\n      score: audit.score,\n      details: audit.details,\n    });\n  }\n\n  return diagnostics;\n}\n","/**\n * @silverassist/performance-toolkit\n *\n * PageSpeed utility functions for data extraction and formatting.\n *\n * @module pagespeed/utils\n * @author Miguel Colmenares <me@miguelcolmenares.com>\n * @license PolyForm-Noncommercial-1.0.0\n */\n\nimport { THIRD_PARTY_PATTERNS } from \"./constants\";\n\n/**\n * Formats cache TTL to human-readable string\n */\nexport function formatCacheTTL(ms: number): string {\n  if (ms === 0) return \"No cache\";\n  const seconds = Math.floor(ms / 1000);\n  if (seconds < 60) return `${seconds}s`;\n  const minutes = Math.floor(seconds / 60);\n  if (minutes < 60) return `${minutes}m`;\n  const hours = Math.floor(minutes / 60);\n  if (hours < 24) return `${hours}h`;\n  const days = Math.floor(hours / 24);\n  if (days < 365) return `${days}d`;\n  const years = Math.floor(days / 365);\n  return `${years}y`;\n}\n\n/**\n * Extracts entity/third-party name from URL\n */\nexport function extractEntityFromUrl(url: string): string | undefined {\n  try {\n    const hostname = new URL(url).hostname;\n\n    for (const [pattern, name] of Object.entries(THIRD_PARTY_PATTERNS)) {\n      if (hostname.includes(pattern)) {\n        return name;\n      }\n    }\n\n    return undefined;\n  } catch {\n    return undefined;\n  }\n}\n\n/**\n * Categorizes third-party by type\n */\nexport function categorizeThirdParty(entity: string): string {\n  const lower = entity.toLowerCase();\n  if (lower.includes(\"analytics\") || lower.includes(\"tag manager\"))\n    return \"analytics\";\n  if (\n    lower.includes(\"facebook\") ||\n    lower.includes(\"twitter\") ||\n    lower.includes(\"linkedin\")\n  )\n    return \"social\";\n  if (lower.includes(\"ad\") || lower.includes(\"doubleclick\"))\n    return \"advertising\";\n  if (\n    lower.includes(\"cdn\") ||\n    lower.includes(\"cloudflare\") ||\n    lower.includes(\"cloudfront\")\n  )\n    return \"cdn\";\n  if (lower.includes(\"font\")) return \"fonts\";\n  if (\n    lower.includes(\"trustedform\") ||\n    lower.includes(\"leadid\") ||\n    lower.includes(\"jornaya\")\n  )\n    return \"lead-tracking\";\n  return \"other\";\n}\n\n/**\n * Checks if URL is first-party\n */\nexport function isFirstParty(url: string, hostDomain: string): boolean {\n  try {\n    const urlHost = new URL(url).hostname;\n    return urlHost.includes(hostDomain) || urlHost === hostDomain;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Gets host domain from URL\n * @param url - The URL to extract domain from\n * @returns The host domain\n */\nexport function getHostDomain(url: string): string {\n  try {\n    return new URL(url).hostname;\n  } catch {\n    return \"\";\n  }\n}\n","/**\n * @silverassist/performance-toolkit\n *\n * Detailed insights extractors for AI agents and actionable data.\n *\n * @module pagespeed/insights\n * @author Miguel Colmenares <me@miguelcolmenares.com>\n * @license PolyForm-Noncommercial-1.0.0\n */\n\nimport type {\n  CacheIssue,\n  DetailedInsights,\n  ImageIssue,\n  LCPBreakdown,\n  LegacyJSIssue,\n  LongTask,\n  PageSpeedResponse,\n  RenderBlockingResource,\n  ThirdPartyIssue,\n  UnusedCodeIssue,\n} from \"../types\";\nimport {\n  formatCacheTTL,\n  extractEntityFromUrl,\n  categorizeThirdParty,\n  isFirstParty,\n  getHostDomain,\n} from \"./utils\";\n\ntype LighthouseAudits = PageSpeedResponse[\"lighthouseResult\"][\"audits\"];\n\n/**\n * Extracts all detailed insights for actionable improvements\n */\nexport function extractDetailedInsights(\n  audits: LighthouseAudits,\n  analyzedUrl?: string,\n): DetailedInsights {\n  const hostDomain = analyzedUrl ? getHostDomain(analyzedUrl) : \"\";\n\n  const cacheIssues = extractCacheIssues(audits);\n  const imageIssues = extractImageIssues(audits);\n  const unusedJavaScript = extractUnusedCode(\n    audits,\n    \"unused-javascript\",\n    hostDomain,\n  );\n  const unusedCSS = extractUnusedCode(audits, \"unused-css-rules\", hostDomain);\n  const legacyJavaScript = extractLegacyJavaScript(audits);\n  const thirdParties = extractThirdParties(audits);\n  const longTasks = extractLongTasks(audits);\n  const renderBlocking = extractRenderBlockingResources(audits);\n  const lcpBreakdown = extractLCPBreakdown(audits);\n\n  // Calculate total savings\n  let totalTimeMs = 0;\n  let totalSizeBytes = 0;\n\n  for (const issue of [...unusedJavaScript, ...unusedCSS]) {\n    totalSizeBytes += issue.wastedBytes;\n  }\n  for (const issue of cacheIssues) {\n    totalSizeBytes += issue.wastedBytes;\n  }\n  for (const issue of imageIssues) {\n    totalSizeBytes += issue.wastedBytes;\n  }\n  for (const resource of renderBlocking) {\n    totalTimeMs += resource.wastedMs;\n  }\n\n  return {\n    lcpBreakdown,\n    cacheIssues,\n    imageIssues,\n    unusedJavaScript,\n    unusedCSS,\n    legacyJavaScript,\n    thirdParties,\n    longTasks,\n    renderBlocking,\n    totalSavings: {\n      timeMs: Math.round(totalTimeMs),\n      sizeBytes: Math.round(totalSizeBytes),\n    },\n  };\n}\n\n/**\n * Extracts resources with poor cache policies\n */\nexport function extractCacheIssues(audits: LighthouseAudits): CacheIssue[] {\n  const audit = audits[\"uses-long-cache-ttl\"];\n  if (!audit?.details?.items) return [];\n\n  const items = audit.details.items as Array<Record<string, unknown>>;\n  const issues: CacheIssue[] = [];\n\n  for (const item of items) {\n    const url = item.url as string;\n    if (!url) continue;\n\n    issues.push({\n      url,\n      cacheTTL: (item.cacheLifetimeMs as number) ?? 0,\n      cacheTTLDisplay: formatCacheTTL((item.cacheLifetimeMs as number) ?? 0),\n      transferSize: (item.totalBytes as number) ?? 0,\n      wastedBytes: (item.wastedBytes as number) ?? 0,\n      entity: extractEntityFromUrl(url),\n    });\n  }\n\n  return issues.sort((a, b) => b.wastedBytes - a.wastedBytes);\n}\n\n/**\n * Extracts image optimization issues from multiple audits\n */\nexport function extractImageIssues(audits: LighthouseAudits): ImageIssue[] {\n  const issues: ImageIssue[] = [];\n  const seenUrls = new Set<string>();\n\n  // Modern image formats (WebP/AVIF)\n  const modernFormats = audits[\"modern-image-formats\"];\n  if (modernFormats?.details?.items) {\n    const items = modernFormats.details.items as Array<Record<string, unknown>>;\n    for (const item of items) {\n      const url = item.url as string;\n      if (!url || seenUrls.has(url)) continue;\n      seenUrls.add(url);\n\n      issues.push({\n        url,\n        totalBytes: (item.totalBytes as number) ?? 0,\n        wastedBytes: (item.wastedBytes as number) ?? 0,\n        issueType: \"format\",\n        recommendation: \"Convert to WebP or AVIF format\",\n        snippet: (item.node as Record<string, unknown>)?.snippet as\n          | string\n          | undefined,\n      });\n    }\n  }\n\n  // Responsive images (oversized)\n  const responsive = audits[\"uses-responsive-images\"];\n  if (responsive?.details?.items) {\n    const items = responsive.details.items as Array<Record<string, unknown>>;\n    for (const item of items) {\n      const url = item.url as string;\n      if (!url || seenUrls.has(url)) continue;\n      seenUrls.add(url);\n\n      issues.push({\n        url,\n        totalBytes: (item.totalBytes as number) ?? 0,\n        wastedBytes: (item.wastedBytes as number) ?? 0,\n        issueType: \"oversized\",\n        recommendation: \"Serve properly sized images for viewport\",\n        snippet: (item.node as Record<string, unknown>)?.snippet as\n          | string\n          | undefined,\n      });\n    }\n  }\n\n  // Offscreen images (lazy load candidates)\n  const offscreen = audits[\"offscreen-images\"];\n  if (offscreen?.details?.items) {\n    const items = offscreen.details.items as Array<Record<string, unknown>>;\n    for (const item of items) {\n      const url = item.url as string;\n      if (!url || seenUrls.has(url)) continue;\n      seenUrls.add(url);\n\n      issues.push({\n        url,\n        totalBytes: (item.totalBytes as number) ?? 0,\n        wastedBytes: (item.wastedBytes as number) ?? 0,\n        issueType: \"offscreen\",\n        recommendation: \"Lazy-load offscreen images with loading='lazy'\",\n        snippet: (item.node as Record<string, unknown>)?.snippet as\n          | string\n          | undefined,\n      });\n    }\n  }\n\n  // Unoptimized images (compression)\n  const unoptimized = audits[\"uses-optimized-images\"];\n  if (unoptimized?.details?.items) {\n    const items = unoptimized.details.items as Array<Record<string, unknown>>;\n    for (const item of items) {\n      const url = item.url as string;\n      if (!url || seenUrls.has(url)) continue;\n      seenUrls.add(url);\n\n      issues.push({\n        url,\n        totalBytes: (item.totalBytes as number) ?? 0,\n        wastedBytes: (item.wastedBytes as number) ?? 0,\n        issueType: \"unoptimized\",\n        recommendation: \"Compress image or use better optimization\",\n        snippet: (item.node as Record<string, unknown>)?.snippet as\n          | string\n          | undefined,\n      });\n    }\n  }\n\n  return issues.sort((a, b) => b.wastedBytes - a.wastedBytes);\n}\n\n/**\n * Extracts unused JavaScript or CSS\n */\nexport function extractUnusedCode(\n  audits: LighthouseAudits,\n  auditId: \"unused-javascript\" | \"unused-css-rules\",\n  hostDomain: string,\n): UnusedCodeIssue[] {\n  const audit = audits[auditId];\n  if (!audit?.details?.items) return [];\n\n  const items = audit.details.items as Array<Record<string, unknown>>;\n  const issues: UnusedCodeIssue[] = [];\n\n  for (const item of items) {\n    const url = item.url as string;\n    if (!url) continue;\n\n    const transferSize = (item.totalBytes as number) ?? 0;\n    const wastedBytes = (item.wastedBytes as number) ?? 0;\n\n    issues.push({\n      url,\n      transferSize,\n      wastedBytes,\n      wastedPercent:\n        transferSize > 0 ? Math.round((wastedBytes / transferSize) * 100) : 0,\n      entity: extractEntityFromUrl(url),\n      isFirstParty: isFirstParty(url, hostDomain),\n    });\n  }\n\n  return issues.sort((a, b) => b.wastedBytes - a.wastedBytes);\n}\n\n/**\n * Extracts legacy JavaScript polyfills\n */\nexport function extractLegacyJavaScript(\n  audits: LighthouseAudits,\n): LegacyJSIssue[] {\n  const audit = audits[\"legacy-javascript\"];\n  if (!audit?.details?.items) return [];\n\n  const items = audit.details.items as Array<Record<string, unknown>>;\n  const issues: LegacyJSIssue[] = [];\n\n  for (const item of items) {\n    const url = item.url as string;\n    if (!url) continue;\n\n    const subItems = item.subItems as\n      | { items?: Array<{ signal?: string }> }\n      | undefined;\n    const polyfills: string[] = [];\n\n    if (subItems?.items) {\n      for (const sub of subItems.items) {\n        if (sub.signal) {\n          polyfills.push(sub.signal);\n        }\n      }\n    }\n\n    issues.push({\n      url,\n      wastedBytes: (item.wastedBytes as number) ?? 0,\n      polyfills,\n      entity: extractEntityFromUrl(url),\n    });\n  }\n\n  return issues.sort((a, b) => b.wastedBytes - a.wastedBytes);\n}\n\n/**\n * Extracts third-party script impact\n */\nexport function extractThirdParties(\n  audits: LighthouseAudits,\n): ThirdPartyIssue[] {\n  const audit = audits[\"third-party-summary\"];\n  if (!audit?.details?.items) return [];\n\n  const items = audit.details.items as Array<Record<string, unknown>>;\n  const issues: ThirdPartyIssue[] = [];\n\n  for (const item of items) {\n    const entity = item.entity as string | { text?: string } | undefined;\n    const entityName =\n      typeof entity === \"string\" ? entity : (entity?.text ?? \"Unknown\");\n\n    // Get URLs from subItems\n    const subItems = item.subItems as\n      | { items?: Array<{ url?: string }> }\n      | undefined;\n    const urls: string[] = [];\n    if (subItems?.items) {\n      for (const sub of subItems.items) {\n        if (sub.url) urls.push(sub.url);\n      }\n    }\n\n    issues.push({\n      entity: entityName,\n      blockingTime: (item.blockingTime as number) ?? 0,\n      transferSize: (item.transferSize as number) ?? 0,\n      requestCount: urls.length,\n      urls,\n      category: categorizeThirdParty(entityName),\n    });\n  }\n\n  return issues.sort((a, b) => b.blockingTime - a.blockingTime);\n}\n\n/**\n * Extracts long tasks blocking main thread\n */\nexport function extractLongTasks(audits: LighthouseAudits): LongTask[] {\n  const audit = audits[\"long-tasks\"];\n  if (!audit?.details?.items) return [];\n\n  const items = audit.details.items as Array<Record<string, unknown>>;\n  const tasks: LongTask[] = [];\n\n  for (const item of items) {\n    tasks.push({\n      duration: (item.duration as number) ?? 0,\n      startTime: (item.startTime as number) ?? 0,\n      url: item.url as string | undefined,\n      attribution: (item.attribution as string) ?? undefined,\n    });\n  }\n\n  return tasks.sort((a, b) => b.duration - a.duration);\n}\n\n/**\n * Extracts render-blocking resources\n */\nexport function extractRenderBlockingResources(\n  audits: LighthouseAudits,\n): RenderBlockingResource[] {\n  const audit = audits[\"render-blocking-resources\"];\n  if (!audit?.details?.items) return [];\n\n  const items = audit.details.items as Array<Record<string, unknown>>;\n  const resources: RenderBlockingResource[] = [];\n\n  for (const item of items) {\n    const url = item.url as string;\n    if (!url) continue;\n\n    let resourceType: RenderBlockingResource[\"resourceType\"] = \"other\";\n    if (url.endsWith(\".js\") || url.includes(\".js?\")) {\n      resourceType = \"script\";\n    } else if (url.endsWith(\".css\") || url.includes(\".css?\")) {\n      resourceType = \"stylesheet\";\n    }\n\n    resources.push({\n      url,\n      transferSize: (item.totalBytes as number) ?? 0,\n      wastedMs: (item.wastedMs as number) ?? 0,\n      resourceType,\n    });\n  }\n\n  return resources.sort((a, b) => b.wastedMs - a.wastedMs);\n}\n\n/**\n * Extracts LCP timing breakdown\n */\nexport function extractLCPBreakdown(\n  audits: LighthouseAudits,\n): LCPBreakdown | undefined {\n  const lcpAudit = audits[\"largest-contentful-paint\"];\n  if (!lcpAudit?.numericValue) return undefined;\n\n  const fcpAudit = audits[\"first-contentful-paint\"];\n  const ttfbAudit = audits[\"server-response-time\"];\n\n  // Get TTFB\n  const ttfb = ttfbAudit?.numericValue ?? 0;\n\n  // Estimate breakdown based on available metrics\n  const totalLcp = lcpAudit.numericValue;\n  const fcp = fcpAudit?.numericValue ?? 0;\n\n  // These are estimates when precise breakdown isn't available\n  const resourceLoadDelay = Math.max(0, fcp - ttfb);\n  const resourceLoadDuration = Math.max(0, (totalLcp - fcp) * 0.6);\n  const elementRenderDelay = Math.max(\n    0,\n    totalLcp - ttfb - resourceLoadDelay - resourceLoadDuration,\n  );\n\n  return {\n    ttfb: Math.round(ttfb),\n    resourceLoadDelay: Math.round(resourceLoadDelay),\n    resourceLoadDuration: Math.round(resourceLoadDuration),\n    elementRenderDelay: Math.round(elementRenderDelay),\n    total: Math.round(totalLcp),\n  };\n}\n","/**\n * @silverassist/performance-toolkit\n *\n * PageSpeed API client for fetching and analyzing performance data.\n *\n * @module pagespeed/client\n * @author Miguel Colmenares <me@miguelcolmenares.com>\n * @license PolyForm-Noncommercial-1.0.0\n */\n\nimport type {\n  Category,\n  PageSpeedOptions,\n  PageSpeedResponse,\n  PerformanceResult,\n  Strategy,\n} from \"../types\";\nimport { PSI_API_URL, DEFAULT_TIMEOUT, DEFAULT_CATEGORIES } from \"./constants\";\nimport {\n  extractScores,\n  extractMetrics,\n  extractLCPElement,\n  extractOpportunities,\n  extractDiagnostics,\n} from \"./extractors\";\nimport { extractDetailedInsights } from \"./insights\";\n\n/**\n * PageSpeed Insights API client for fetching performance data\n */\nexport class PageSpeedClient {\n  private apiKey?: string;\n  private timeout: number;\n\n  /**\n   * Creates a new PageSpeed client\n   * @param apiKey - Optional API key for higher rate limits\n   * @param timeout - Request timeout in milliseconds\n   */\n  constructor(apiKey?: string, timeout = DEFAULT_TIMEOUT) {\n    this.apiKey = apiKey;\n    this.timeout = timeout;\n  }\n\n  /**\n   * Analyzes a URL using PageSpeed Insights API\n   * @param options - Analysis options\n   * @returns Performance analysis result\n   */\n  async analyze(options: PageSpeedOptions): Promise<PerformanceResult> {\n    const {\n      url,\n      strategy = \"mobile\",\n      categories = DEFAULT_CATEGORIES,\n      apiKey = this.apiKey,\n      timeout = this.timeout,\n    } = options;\n\n    const apiUrl = this.buildApiUrl(url, strategy, categories, apiKey);\n    const response = await this.fetchWithTimeout(apiUrl, timeout);\n    const data = (await response.json()) as PageSpeedResponse;\n\n    return this.transformResponse(data, url, strategy);\n  }\n\n  /**\n   * Analyzes a URL for both mobile and desktop\n   * @param url - URL to analyze\n   * @param categories - Categories to analyze\n   * @returns Object with mobile and desktop results\n   */\n  async analyzeAll(\n    url: string,\n    categories: Category[] = DEFAULT_CATEGORIES,\n  ): Promise<{ mobile: PerformanceResult; desktop: PerformanceResult }> {\n    const [mobile, desktop] = await Promise.all([\n      this.analyze({ url, strategy: \"mobile\", categories }),\n      this.analyze({ url, strategy: \"desktop\", categories }),\n    ]);\n\n    return { mobile, desktop };\n  }\n\n  /**\n   * Builds the PageSpeed API URL with query parameters\n   */\n  private buildApiUrl(\n    url: string,\n    strategy: Strategy,\n    categories: Category[],\n    apiKey?: string,\n  ): string {\n    const params = new URLSearchParams();\n    params.append(\"url\", url);\n    params.append(\"strategy\", strategy.toUpperCase());\n\n    // Add each category separately (API requires separate params)\n    for (const category of categories) {\n      params.append(\"category\", category.toUpperCase().replace(\"-\", \"_\"));\n    }\n\n    if (apiKey) {\n      params.append(\"key\", apiKey);\n    }\n\n    return `${PSI_API_URL}?${params.toString()}`;\n  }\n\n  /**\n   * Fetches URL with timeout using AbortController\n   */\n  private async fetchWithTimeout(\n    url: string,\n    timeout: number,\n  ): Promise<Response> {\n    const controller = new AbortController();\n    const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n    try {\n      const response = await fetch(url, { signal: controller.signal });\n\n      if (!response.ok) {\n        throw new Error(\n          `PageSpeed API error: ${response.status} ${response.statusText}`,\n        );\n      }\n\n      return response;\n    } finally {\n      clearTimeout(timeoutId);\n    }\n  }\n\n  /**\n   * Transforms PageSpeed API response to PerformanceResult\n   */\n  private transformResponse(\n    data: PageSpeedResponse,\n    url: string,\n    strategy: Strategy,\n  ): PerformanceResult {\n    const { lighthouseResult, loadingExperience } = data;\n\n    return {\n      url,\n      strategy,\n      timestamp: data.analysisUTCTimestamp,\n      scores: extractScores(lighthouseResult),\n      metrics: extractMetrics(lighthouseResult),\n      lcpElement: extractLCPElement(lighthouseResult),\n      opportunities: extractOpportunities(lighthouseResult),\n      diagnostics: extractDiagnostics(lighthouseResult),\n      insights: extractDetailedInsights(lighthouseResult.audits, url),\n      fieldData: loadingExperience,\n      rawResponse: data,\n    };\n  }\n}\n\n/**\n * Creates a configured PageSpeed client instance\n * @param apiKey - Optional API key\n * @returns Configured PageSpeedClient instance\n */\nexport function createPageSpeedClient(apiKey?: string): PageSpeedClient {\n  return new PageSpeedClient(apiKey);\n}\n\n/**\n * Quick function to analyze a single URL\n * @param url - URL to analyze\n * @param options - Analysis options\n * @returns Performance result\n */\nexport async function analyzeUrl(\n  url: string,\n  options: Omit<PageSpeedOptions, \"url\"> = {},\n): Promise<PerformanceResult> {\n  const client = new PageSpeedClient(options.apiKey, options.timeout);\n  return client.analyze({ url, ...options });\n}\n"]}