/** * Player headshot URL construction — PURE core (Wave 2A). * * CommonJS on purpose: importable by the `.ts` resolver (`playerHeadshot.ts`, * allowJs) AND requireable by the plain-JS Jest suite — same doctrine as * `vyndrTokens.js` / `playerName.js`. Keep the URL logic HERE so it stays * genuinely unit-testable (jest can't transform the `.ts`). * * Each league hosts its own CDN. Fallback chain inside the resolver: * 1. `cachedPhotoUrl` — a stored URL (soccer, where API-Football returns the * photo). We DO NOT construct soccer URLs (no central CDN). * 2. League CDN with `playerId` — official source. * 3. ESPN CDN with `espnId` — NBA/WNBA (and dormant NFL/NHL) headshots. * 4. `/images/player-silhouette.svg` — the sentinel the component swaps for a * team-colored MONOGRAM (never a gray blob, never a broken image). */ const PLAYER_SILHOUETTE = '/images/player-silhouette.svg'; const ESPN_SPORT_PATH = { nba: 'nba', wnba: 'wnba', mlb: 'mlb', // Wave 2A — dormant leagues (not in ACTIVE_SPORTS + off-season). Cheap // correctness: an ESPN athlete id ingested later resolves for free. nfl: 'nfl', nhl: 'nhl', // ESPN soccer headshots are inconsistent across leagues — explicitly omit so // soccer falls through to the silhouette unless a cached photo is provided. }; function getHeadshotUrl(input) { input = input || {}; const sport = String(input.sport || '').toLowerCase(); const playerId = input.playerId != null ? String(input.playerId) : ''; const espnId = input.espnId != null ? String(input.espnId) : ''; const cached = input.cachedPhotoUrl ? String(input.cachedPhotoUrl) : ''; if (cached) return cached; if (playerId) { switch (sport) { case 'nba': return `https://cdn.nba.com/headshots/nba/latest/260x190/${playerId}.png`; case 'wnba': return `https://cdn.wnba.com/headshots/wnba/latest/260x190/${playerId}.png`; case 'mlb': return `https://img.mlbstatic.com/mlb-photos/image/upload/d_people:generic:headshot:67:current.png/w_213,q_auto:best/v1/people/${playerId}/headshot/67/current`; default: break; } } if (espnId && ESPN_SPORT_PATH[sport]) { return `https://a.espncdn.com/combiner/i?img=/i/headshots/${ESPN_SPORT_PATH[sport]}/players/full/${espnId}.png&w=130&h=95`; } return PLAYER_SILHOUETTE; } module.exports = { PLAYER_SILHOUETTE, ESPN_SPORT_PATH, getHeadshotUrl };