fansunited-data-layer 0.13.0 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/fansunited/constants.js +5 -0
- package/api/fansunited/constants.js.map +1 -0
- package/api/fansunited/football/competition/index.js +21 -0
- package/api/fansunited/football/competition/index.js.map +1 -0
- package/api/fansunited/football/competition/transformer.js +41 -0
- package/api/fansunited/football/competition/transformer.js.map +1 -0
- package/api/fansunited/football/competitions/index.js +56 -0
- package/api/fansunited/football/competitions/index.js.map +1 -0
- package/api/fansunited/football/competitions/transformer.js +68 -0
- package/api/fansunited/football/competitions/transformer.js.map +1 -0
- package/api/fansunited/football/http.js +7 -0
- package/api/fansunited/football/http.js.map +1 -0
- package/api/fansunited/football/matches/index.js +132 -0
- package/api/fansunited/football/matches/index.js.map +1 -0
- package/api/fansunited/football/matches/transformer.js +148 -0
- package/api/fansunited/football/matches/transformer.js.map +1 -0
- package/api/fansunited/football/players/index.js +60 -0
- package/api/fansunited/football/players/index.js.map +1 -0
- package/api/fansunited/football/players/transformer.js +85 -0
- package/api/fansunited/football/players/transformer.js.map +1 -0
- package/api/fansunited/football/search/index.js +64 -0
- package/api/fansunited/football/search/index.js.map +1 -0
- package/api/fansunited/football/search/transformer.js +114 -0
- package/api/fansunited/football/search/transformer.js.map +1 -0
- package/api/fansunited/football/teams/index.js +66 -0
- package/api/fansunited/football/teams/index.js.map +1 -0
- package/api/fansunited/football/teams/transformer.js +53 -0
- package/api/fansunited/football/teams/transformer.js.map +1 -0
- package/api/fansunited/http.d.ts.map +1 -1
- package/api/fansunited/http.js +70 -0
- package/api/fansunited/http.js.map +1 -0
- package/api/fansunited/search/constants.js +5 -0
- package/api/fansunited/search/constants.js.map +1 -0
- package/api/fansunited/search/http.js +7 -0
- package/api/fansunited/search/http.js.map +1 -0
- package/api/fansunited/search/index.js +308 -0
- package/api/fansunited/search/index.js.map +1 -0
- package/api/fansunited/search/transformer.js +374 -0
- package/api/fansunited/search/transformer.js.map +1 -0
- package/api/fansunited-sdk/loyalty/matches.js +21 -0
- package/api/fansunited-sdk/loyalty/matches.js.map +1 -0
- package/api/fansunited-sdk/loyalty/template.js +52 -0
- package/api/fansunited-sdk/loyalty/template.js.map +1 -0
- package/api/fansunited-sdk/odds/matches.js +109 -0
- package/api/fansunited-sdk/odds/matches.js.map +1 -0
- package/api/sportal365-sports/basketball/games/index.js +32 -0
- package/api/sportal365-sports/basketball/games/index.js.map +1 -0
- package/api/sportal365-sports/basketball/games/transformers/game.js +137 -0
- package/api/sportal365-sports/basketball/games/transformers/game.js.map +1 -0
- package/api/sportal365-sports/basketball/http.js +7 -0
- package/api/sportal365-sports/basketball/http.js.map +1 -0
- package/api/sportal365-sports/constants.js +15 -0
- package/api/sportal365-sports/constants.js.map +1 -0
- package/api/sportal365-sports/football/competitions/index.js +52 -0
- package/api/sportal365-sports/football/competitions/index.js.map +1 -0
- package/api/sportal365-sports/football/competitions/utils.js +92 -0
- package/api/sportal365-sports/football/competitions/utils.js.map +1 -0
- package/api/sportal365-sports/football/http.js +7 -0
- package/api/sportal365-sports/football/http.js.map +1 -0
- package/api/sportal365-sports/football/matches/index.js +206 -0
- package/api/sportal365-sports/football/matches/index.js.map +1 -0
- package/api/sportal365-sports/football/matches/transformers/commentary.js +27 -0
- package/api/sportal365-sports/football/matches/transformers/commentary.js.map +1 -0
- package/api/sportal365-sports/football/matches/transformers/lineup.js +74 -0
- package/api/sportal365-sports/football/matches/transformers/lineup.js.map +1 -0
- package/api/sportal365-sports/football/matches/transformers/match-event.js +60 -0
- package/api/sportal365-sports/football/matches/transformers/match-event.js.map +1 -0
- package/api/sportal365-sports/football/matches/transformers/match.js +195 -0
- package/api/sportal365-sports/football/matches/transformers/match.js.map +1 -0
- package/api/sportal365-sports/football/matches/transformers/odds.js +11 -0
- package/api/sportal365-sports/football/matches/transformers/odds.js.map +1 -0
- package/api/sportal365-sports/football/matches/transformers/statistics.js +41 -0
- package/api/sportal365-sports/football/matches/transformers/statistics.js.map +1 -0
- package/api/sportal365-sports/football/search/index.js +42 -0
- package/api/sportal365-sports/football/search/index.js.map +1 -0
- package/api/sportal365-sports/football/search/search.transformer.js +166 -0
- package/api/sportal365-sports/football/search/search.transformer.js.map +1 -0
- package/api/sportal365-sports/football/standings/index.js +28 -0
- package/api/sportal365-sports/football/standings/index.js.map +1 -0
- package/api/sportal365-sports/football/standings/standing.transformer.js +107 -0
- package/api/sportal365-sports/football/standings/standing.transformer.js.map +1 -0
- package/api/sportal365-sports/football/statistics/index.js +154 -0
- package/api/sportal365-sports/football/statistics/index.js.map +1 -0
- package/api/sportal365-sports/football/statistics/player-career.transformer.js +77 -0
- package/api/sportal365-sports/football/statistics/player-career.transformer.js.map +1 -0
- package/api/sportal365-sports/football/statistics/player-recent.transformer.js +54 -0
- package/api/sportal365-sports/football/statistics/player-recent.transformer.js.map +1 -0
- package/api/sportal365-sports/football/statistics/player-season.transformer.js +147 -0
- package/api/sportal365-sports/football/statistics/player-season.transformer.js.map +1 -0
- package/api/sportal365-sports/football/teams/index.js +73 -0
- package/api/sportal365-sports/football/teams/index.js.map +1 -0
- package/api/sportal365-sports/football/teams/utils.js +196 -0
- package/api/sportal365-sports/football/teams/utils.js.map +1 -0
- package/api/sportal365-sports/http.js +58 -0
- package/api/sportal365-sports/http.js.map +1 -0
- package/api/sportal365-sports/search/http.js +7 -0
- package/api/sportal365-sports/search/http.js.map +1 -0
- package/api/sportal365-sports/search/index.js +61 -0
- package/api/sportal365-sports/search/index.js.map +1 -0
- package/api/sportal365-sports/search/search.transformer.js +254 -0
- package/api/sportal365-sports/search/search.transformer.js.map +1 -0
- package/api/sportal365-sports/shared/odds.transformer.js +65 -0
- package/api/sportal365-sports/shared/odds.transformer.js.map +1 -0
- package/api/sportal365-sports/shared/providerRef.helper.js +31 -0
- package/api/sportal365-sports/shared/providerRef.helper.js.map +1 -0
- package/api/sportal365-sports/standings/http.js +7 -0
- package/api/sportal365-sports/standings/http.js.map +1 -0
- package/api/sportal365-sports/standings/index.js +29 -0
- package/api/sportal365-sports/standings/index.js.map +1 -0
- package/api/sportal365-sports/standings/standing.transformer.js +185 -0
- package/api/sportal365-sports/standings/standing.transformer.js.map +1 -0
- package/api/sportal365-sports/statistics/http.js +7 -0
- package/api/sportal365-sports/statistics/http.js.map +1 -0
- package/api/sportal365-sports/statistics/index.js +25 -0
- package/api/sportal365-sports/statistics/index.js.map +1 -0
- package/api/sportal365-sports/statistics/team-stats.transformer.js +16 -0
- package/api/sportal365-sports/statistics/team-stats.transformer.js.map +1 -0
- package/api/sportal365-sports/tennis/http.js +7 -0
- package/api/sportal365-sports/tennis/http.js.map +1 -0
- package/api/sportal365-sports/tennis/matches/index.js +34 -0
- package/api/sportal365-sports/tennis/matches/index.js.map +1 -0
- package/api/sportal365-sports/tennis/matches/transformers/match.js +193 -0
- package/api/sportal365-sports/tennis/matches/transformers/match.js.map +1 -0
- package/cache/cache-manager.js +136 -0
- package/cache/cache-manager.js.map +1 -0
- package/cache/memory-store.js +29 -0
- package/cache/memory-store.js.map +1 -0
- package/client.js +38 -12337
- package/client.js.map +1 -0
- package/config/index.js +20 -0
- package/config/index.js.map +1 -0
- package/fansunited-data-layer.js +146 -3553
- package/fansunited-data-layer.js.map +1 -0
- package/helpers/competition.helpers.js +11 -0
- package/helpers/competition.helpers.js.map +1 -0
- package/helpers/player.helpers.js +165 -0
- package/helpers/player.helpers.js.map +1 -0
- package/helpers/player.hooks.js +34 -0
- package/helpers/player.hooks.js.map +1 -0
- package/helpers/team.helpers.js +216 -0
- package/helpers/team.helpers.js.map +1 -0
- package/package.json +6 -8
- package/providers/competition/hooks/useCompetitionStats.js +10 -0
- package/providers/competition/hooks/useCompetitionStats.js.map +1 -0
- package/providers/competition/hooks/useGoalDistribution.js +23 -0
- package/providers/competition/hooks/useGoalDistribution.js.map +1 -0
- package/providers/competition/hooks/useMatchHelpers.js +85 -0
- package/providers/competition/hooks/useMatchHelpers.js.map +1 -0
- package/providers/competition/hooks/useStandingsCalculations.js +89 -0
- package/providers/competition/hooks/useStandingsCalculations.js.map +1 -0
- package/providers/competition/hooks/useStandingsHelpers.js +61 -0
- package/providers/competition/hooks/useStandingsHelpers.js.map +1 -0
- package/providers/competition/hooks/useTeamPosition.js +15 -0
- package/providers/competition/hooks/useTeamPosition.js.map +1 -0
- package/providers/competition/hooks/useTeamResultsTable.js +86 -0
- package/providers/competition/hooks/useTeamResultsTable.js.map +1 -0
- package/providers/competition/utils/competitionStats.js +109 -0
- package/providers/competition/utils/competitionStats.js.map +1 -0
- package/providers/competition/utils/goalDistribution.js +64 -0
- package/providers/competition/utils/goalDistribution.js.map +1 -0
- package/providers/competition/utils/standingsCalculations.js +152 -0
- package/providers/competition/utils/standingsCalculations.js.map +1 -0
- package/providers/competition.context.js +14 -0
- package/providers/competition.context.js.map +1 -0
- package/providers/competition.provider.js +187 -0
- package/providers/competition.provider.js.map +1 -0
- package/providers/fansunited-config.context.js +6 -0
- package/providers/fansunited-config.context.js.map +1 -0
- package/providers/fansunited-config.hooks.js +20 -0
- package/providers/fansunited-config.hooks.js.map +1 -0
- package/providers/fansunited-config.provider.js +9 -0
- package/providers/fansunited-config.provider.js.map +1 -0
- package/providers/fansunited-sdk.hook.js +50 -0
- package/providers/fansunited-sdk.hook.js.map +1 -0
- package/providers/leaderboard/hooks/useMatchHelpers.js +30 -0
- package/providers/leaderboard/hooks/useMatchHelpers.js.map +1 -0
- package/providers/leaderboard/hooks/useTemplateHelpers.js +39 -0
- package/providers/leaderboard/hooks/useTemplateHelpers.js.map +1 -0
- package/providers/leaderboard.context.js +14 -0
- package/providers/leaderboard.context.js.map +1 -0
- package/providers/leaderboard.provider.js +98 -0
- package/providers/leaderboard.provider.js.map +1 -0
- package/providers/match/hooks/useBatchMatchOdds.js +72 -0
- package/providers/match/hooks/useBatchMatchOdds.js.map +1 -0
- package/providers/match/hooks/useEventHelpers.js +46 -0
- package/providers/match/hooks/useEventHelpers.js.map +1 -0
- package/providers/match/hooks/useHeadToHeadHelpers.js +52 -0
- package/providers/match/hooks/useHeadToHeadHelpers.js.map +1 -0
- package/providers/match/hooks/useLineupHelpers.js +53 -0
- package/providers/match/hooks/useLineupHelpers.js.map +1 -0
- package/providers/match/hooks/useMatchStandingsCalculations.js +332 -0
- package/providers/match/hooks/useMatchStandingsCalculations.js.map +1 -0
- package/providers/match/hooks/useMatchStatus.js +37 -0
- package/providers/match/hooks/useMatchStatus.js.map +1 -0
- package/providers/match/hooks/useOddsHelpers.js +54 -0
- package/providers/match/hooks/useOddsHelpers.js.map +1 -0
- package/providers/match/hooks/useScoreHelpers.js +34 -0
- package/providers/match/hooks/useScoreHelpers.js.map +1 -0
- package/providers/match/hooks/useStandingsHelpers.js +53 -0
- package/providers/match/hooks/useStandingsHelpers.js.map +1 -0
- package/providers/match/hooks/useStatisticsHelpers.js +40 -0
- package/providers/match/hooks/useStatisticsHelpers.js.map +1 -0
- package/providers/match/hooks/useTeamHelpers.js +38 -0
- package/providers/match/hooks/useTeamHelpers.js.map +1 -0
- package/providers/match/hooks/useTeamStatsHelpers.js +141 -0
- package/providers/match/hooks/useTeamStatsHelpers.js.map +1 -0
- package/providers/match.context.js +14 -0
- package/providers/match.context.js.map +1 -0
- package/providers/match.provider.js +176 -0
- package/providers/match.provider.js.map +1 -0
- package/providers/team/hooks/useFormStats.js +116 -0
- package/providers/team/hooks/useFormStats.js.map +1 -0
- package/providers/team/hooks/useMatchHelpers.js +46 -0
- package/providers/team/hooks/useMatchHelpers.js.map +1 -0
- package/providers/team/hooks/useSquadHelpers.js +67 -0
- package/providers/team/hooks/useSquadHelpers.js.map +1 -0
- package/providers/team.context.js +14 -0
- package/providers/team.context.js.map +1 -0
- package/providers/team.provider.js +98 -0
- package/providers/team.provider.js.map +1 -0
- package/utilities/stats/core/helpers.js +105 -0
- package/utilities/stats/core/helpers.js.map +1 -0
- package/utilities/stats/core/types.js +5 -0
- package/utilities/stats/core/types.js.map +1 -0
- package/utilities/stats/match/headToHead.js +83 -0
- package/utilities/stats/match/headToHead.js.map +1 -0
- package/utilities/stats/match/homeVsAway.js +140 -0
- package/utilities/stats/match/homeVsAway.js.map +1 -0
- package/utilities/stats/match/overUnder.js +91 -0
- package/utilities/stats/match/overUnder.js.map +1 -0
- package/utilities/stats/match/result.js +21 -0
- package/utilities/stats/match/result.js.map +1 -0
- package/utilities/stats/team/commonOpponents.js +77 -0
- package/utilities/stats/team/commonOpponents.js.map +1 -0
- package/utilities/stats/team/goalStats.js +50 -0
- package/utilities/stats/team/goalStats.js.map +1 -0
- package/utilities/stats/team/streaks.js +183 -0
- package/utilities/stats/team/streaks.js.map +1 -0
- package/client.cjs +0 -8
- package/fansunited-data-layer.cjs +0 -1
- package/matches-BvHU-bP0.js +0 -1795
- package/matches-Ci0Ci_Mw.cjs +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/lib/api/sportal365-sports/football/matches/index.ts"],"sourcesContent":["/**\n * Sportal365 Sports API - Football Matches\n *\n * Fetches match data and transforms to canonical FUSports types.\n */\n\nimport type {\n FUSportsMatch,\n FUSportsMatchEvent,\n FUSportsMatchLineups,\n FUSportsMatchStatistics,\n FUSportsMatchOdds,\n FUSportsCommentaryItem,\n} from \"../../../../types/canonical\";\nimport { getConfig, type DataLayerConfig } from \"../../../../config\";\nimport { footballHttp } from \"../http\";\nimport type {\n RawMatch,\n RawMatchEvent,\n RawMatchLineups,\n RawMatchStatisticsResponse,\n RawCommentary,\n GetFootballMatchOptions,\n GetFootballMatchEventsOptions,\n GetFootballMatchLineupsOptions,\n GetFootballMatchOddsOptions,\n GetFootballMatchStatisticsOptions,\n GetFootballMatchCommentaryOptions,\n GetFootballMatchesOptions,\n GetFootballLivescoreOptions,\n} from \"./types\";\nimport {\n transformMatch,\n transformEvent,\n transformLineups,\n transformStatistics,\n transformMatchOdds,\n transformCommentary,\n} from \"./transformers\";\n\n// Re-export types for options\nexport type {\n GetFootballMatchOptions,\n GetFootballMatchEventsOptions,\n GetFootballMatchLineupsOptions,\n GetFootballMatchOddsOptions,\n GetFootballMatchStatisticsOptions,\n GetFootballMatchCommentaryOptions,\n GetFootballMatchesOptions,\n GetFootballLivescoreOptions,\n OddType,\n ScopeType,\n OddFormat,\n MarketType,\n OptionalMatchData,\n MatchStatusType,\n SortDirection,\n SelectionFilter,\n} from \"./types\";\n\n/**\n * Get a football match by ID, UUID, or slug\n *\n * @param matchId - The match ID, UUID, or slug\n * @param options - Optional parameters for odds, events, lineups\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Canonical FUSportsMatch\n *\n * @example\n * ```typescript\n * // Basic usage\n * const match = await getFootballMatch('7576255');\n * console.log(match.competitorOne.name); // \"Manchester United\"\n *\n * // With main events and lineup status\n * const match = await getFootballMatch('7576255', {\n * optionalData: ['MAIN_EVENTS', 'LINEUP_STATUS']\n * });\n * console.log(match.mainEvents); // Goals, cards, etc.\n * ```\n */\nexport async function getFootballMatch(\n matchId: string,\n options?: GetFootballMatchOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatch> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<RawMatch>({\n path: `/v2/matches/${matchId}`,\n params: {\n language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n odd_client: options?.oddClient,\n odd_type: options?.oddType,\n scope_type: options?.scopeType,\n odd_format: options?.oddFormat,\n market_types: options?.marketTypes,\n bookmaker_ids: options?.bookmakerIds,\n optional_data: options?.optionalData,\n },\n headers: {\n \"Accept-Language\": options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options?.next,\n config: finalConfig,\n });\n\n return transformMatch(raw);\n}\n\n/**\n * Get all events for a football match\n *\n * @param matchId - The match ID\n * @param options - Optional parameters\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Array of match events (goals, cards, substitutions, etc.)\n *\n * @example\n * ```typescript\n * const events = await getFootballMatchEvents('7576255');\n * events.forEach(e => console.log(`${e.minute}' - ${e.type}`));\n * ```\n */\nexport async function getFootballMatchEvents(\n matchId: string,\n options?: GetFootballMatchEventsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatchEvent[]> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<{ events: RawMatchEvent[] }>({\n path: `/v2/matches/${matchId}/events`,\n params: {\n language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n headers: {\n \"Accept-Language\": options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options?.next,\n config: finalConfig,\n });\n\n return raw.events.map(transformEvent).filter((e): e is FUSportsMatchEvent => e !== null);\n}\n\n/**\n * Get lineups for a football match\n *\n * @param matchId - The match ID\n * @param options - Optional parameters\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Canonical match lineups with formations and players\n *\n * @example\n * ```typescript\n * const lineups = await getFootballMatchLineups('7576255');\n * console.log(lineups.home.formation); // \"4-3-3\"\n * console.log(lineups.home.starters);\n * ```\n */\nexport async function getFootballMatchLineups(\n matchId: string,\n options?: GetFootballMatchLineupsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatchLineups> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<RawMatchLineups>({\n path: `/v2/matches/${matchId}/lineups`,\n params: {\n language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n headers: {\n \"Accept-Language\": options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options?.next,\n config: finalConfig,\n });\n\n return transformLineups(raw);\n}\n\n/**\n * Get odds for a football match\n *\n * Odds are fetched from the match endpoint with odds parameters.\n * Uses `oddClient` and `languageCode` from config if not provided in options.\n *\n * @param matchId - The match ID\n * @param options - Optional parameters for filtering odds\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Canonical match odds with bookmaker details\n *\n * @example\n * ```typescript\n * const odds = await getFootballMatchOdds('7576255', {\n * marketTypes: ['1x2', 'OVER_UNDER']\n * });\n * console.log(`${odds.bookmakers.length} bookmakers available`);\n * ```\n */\nexport async function getFootballMatchOdds(\n matchId: string,\n options?: GetFootballMatchOddsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatchOdds> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<RawMatch>({\n path: `/v2/matches/${matchId}`,\n params: {\n language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n odd_client: options?.oddClient ?? sportal365Sports?.oddClient,\n odd_type: options?.oddType,\n scope_type: options?.scopeType ?? \"ALL\",\n odd_format: options?.oddFormat ?? \"DECIMAL\",\n market_types: options?.marketTypes,\n bookmaker_ids: options?.bookmakerIds,\n },\n headers: {\n \"Accept-Language\": options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options?.next,\n config: finalConfig,\n });\n\n return transformMatchOdds(matchId, raw.odds ?? []);\n}\n\n/**\n * Get team statistics for a football match\n *\n * @param matchId - The match ID (event ID)\n * @param options - Optional parameters\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Canonical match statistics for both teams\n *\n * @example\n * ```typescript\n * const stats = await getFootballMatchStatistics('7576255');\n * console.log(`Possession: ${stats.home.possession}% - ${stats.away.possession}%`);\n * console.log(`Shots: ${stats.home.shotsTotal} - ${stats.away.shotsTotal}`);\n * ```\n */\nexport async function getFootballMatchStatistics(\n matchId: string,\n options?: GetFootballMatchStatisticsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatchStatistics> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<RawMatchStatisticsResponse>({\n path: `/events/${matchId}/teamstats`,\n params: {\n language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n headers: {\n \"Accept-Language\": options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options?.next,\n config: finalConfig,\n });\n\n return transformStatistics(raw);\n}\n\n/**\n * Get live commentary for a football match\n *\n * @param matchId - The match ID, UUID, or slug\n * @param options - Optional parameters\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Array of commentary entries\n *\n * @example\n * ```typescript\n * const commentary = await getFootballMatchCommentary('7576255');\n * commentary.forEach(c => {\n * console.log(`${c.elapsed}' - ${c.autoText}`);\n * });\n * ```\n */\nexport async function getFootballMatchCommentary(\n matchId: string,\n options?: GetFootballMatchCommentaryOptions,\n config?: DataLayerConfig\n): Promise<FUSportsCommentaryItem[]> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<RawCommentary[]>({\n path: `/matches/${matchId}/commentary`,\n params: {\n language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n headers: {\n \"Accept-Language\": options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options?.next,\n config: finalConfig,\n });\n\n return raw.map(transformCommentary);\n}\n\n/**\n * Get a list of football matches\n *\n * @param options - Filter and pagination options (limit and offset are required)\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Array of canonical FUSportsMatch objects\n *\n * @example\n * ```typescript\n * // Get 10 upcoming matches for a specific tournament\n * const matches = await getFootballMatches({\n * tournamentIds: ['123'],\n * fromKickoffTime: new Date().toISOString(),\n * sortDirection: 'asc',\n * limit: 10,\n * offset: 0\n * });\n *\n * // Get matches by team\n * const teamMatches = await getFootballMatches({\n * teamIds: ['102', '103'],\n * teamIdsOperator: 'OR',\n * limit: 20,\n * offset: 0\n * });\n *\n * // Get live matches\n * const liveMatches = await getFootballMatches({\n * statusTypes: ['LIVE'],\n * limit: 50,\n * offset: 0\n * });\n * ```\n */\nexport async function getFootballMatches(\n options: GetFootballMatchesOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatch[]> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<{ matches: RawMatch[] }>({\n path: `/v2/matches`,\n params: {\n language_code: options.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n limit: options.limit.toString(),\n offset: options.offset.toString(),\n\n // Competition filters\n tournament_ids: options.tournamentIds,\n season_ids: options.seasonIds,\n stage_ids: options.stageIds,\n group_ids: options.groupIds,\n round_ids: options.roundIds,\n round_filter: options.roundFilter,\n\n // Time filters\n from_kickoff_time: options.fromKickoffTime,\n to_kickoff_time: options.toKickoffTime,\n\n // Entity filters\n team_ids: options.teamIds,\n team_ids_operator: options.teamIdsOperator,\n referee_id: options.refereeId,\n venue_id: options.venueId,\n player_id: options.playerId,\n\n // Status filters\n status_types: options.statusTypes,\n status_codes: options.statusCodes,\n\n // Odds\n odd_client: options.oddClient ?? sportal365Sports?.oddClient,\n odd_type: options.oddType,\n scope_type: options.scopeType,\n odd_format: options.oddFormat,\n market_types: options.marketTypes,\n bookmaker_ids: options.bookmakerIds,\n\n // Sorting and optional data\n sort_direction: options.sortDirection,\n optional_data: options.optionalData,\n },\n headers: {\n \"Accept-Language\": options.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options.next,\n config: finalConfig,\n });\n\n return raw.matches.map(transformMatch);\n}\n\n/**\n * Get livescore matches\n *\n * This endpoint is optimized for livescore use cases and provides a simpler\n * interface compared to the general matches endpoint. It's designed for\n * fetching matches by date, tournament group, or status.\n *\n * @param options - Filter options for livescore matches\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Array of canonical FUSportsMatch objects\n *\n * @example\n * ```typescript\n * // Get all live matches\n * const liveMatches = await getFootballLivescore({\n * statusTypes: ['LIVE']\n * });\n *\n * // Get matches for a specific date\n * const todayMatches = await getFootballLivescore({\n * date: '2024-01-15',\n * utcOffset: 2\n * });\n *\n * // Get matches for a tournament group with main events\n * const premierLeague = await getFootballLivescore({\n * tournamentGroup: 'premier_league',\n * optionalData: 'MAIN_EVENTS'\n * });\n *\n * // Get specific matches by IDs\n * const matches = await getFootballLivescore({\n * matchIds: ['7576255', '7576256']\n * });\n * ```\n */\nexport async function getFootballLivescore(\n options?: GetFootballLivescoreOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatch[]> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await footballHttp.get<{ matches: RawMatch[] }>({\n path: `/v2/matches/livescore`,\n params: {\n // Match filters\n match_ids: options?.matchIds,\n date: options?.date,\n utc_offset: options?.utcOffset?.toString(),\n tournament_group: options?.tournamentGroup,\n status_types: options?.statusTypes,\n selection_filter: options?.selectionFilter,\n language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n\n // Odds parameters\n odd_client: options?.oddClient ?? sportal365Sports?.oddClient,\n odd_type: options?.oddType,\n scope_type: options?.scopeType,\n odd_format: options?.oddFormat,\n market_types: options?.marketTypes,\n\n // Optional data\n optional_data: options?.optionalData,\n },\n headers: {\n \"Accept-Language\": options?.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options?.next,\n config: finalConfig,\n });\n\n return raw.matches.map(transformMatch);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function parseNumber(value) {
|
|
2
|
+
if (value === void 0 || value === null || value === "") {
|
|
3
|
+
return void 0;
|
|
4
|
+
}
|
|
5
|
+
const num = typeof value === "number" ? value : parseInt(value, 10);
|
|
6
|
+
return isNaN(num) ? void 0 : num;
|
|
7
|
+
}
|
|
8
|
+
function transformCommentary(raw) {
|
|
9
|
+
return {
|
|
10
|
+
externalId: raw.external_id,
|
|
11
|
+
minute: parseNumber(raw.elapsed),
|
|
12
|
+
addedTime: parseNumber(raw.elapsed_plus),
|
|
13
|
+
text: raw.auto_text,
|
|
14
|
+
details: raw.details,
|
|
15
|
+
meta: {
|
|
16
|
+
type: raw.type,
|
|
17
|
+
commentaryType: raw.commentary_type,
|
|
18
|
+
subtype1: raw.subtype_1,
|
|
19
|
+
subtype2: raw.subtype_2,
|
|
20
|
+
timestamp: raw.incident_timestamp
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
transformCommentary
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=commentary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentary.js","sources":["../../../../../../src/lib/api/sportal365-sports/football/matches/transformers/commentary.ts"],"sourcesContent":["/**\n * Commentary transformers\n *\n * Transforms raw API commentary data to canonical FUSportsCommentary type.\n */\n\nimport type { FUSportsCommentaryItem } from \"../../../../../types/canonical\";\nimport type { RawCommentary } from \"../types\";\n\n/**\n * Parse a string or number to a number, returning undefined if invalid\n */\nfunction parseNumber(value: string | number | undefined): number | undefined {\n if (value === undefined || value === null || value === \"\") {\n return undefined;\n }\n const num = typeof value === \"number\" ? value : parseInt(value, 10);\n return isNaN(num) ? undefined : num;\n}\n\n/**\n * Transform raw commentary entry to canonical format\n */\nexport function transformCommentary(raw: RawCommentary): FUSportsCommentaryItem {\n return {\n externalId: raw.external_id,\n minute: parseNumber(raw.elapsed),\n addedTime: parseNumber(raw.elapsed_plus),\n text: raw.auto_text,\n details: raw.details,\n meta: {\n type: raw.type,\n commentaryType: raw.commentary_type,\n subtype1: raw.subtype_1,\n subtype2: raw.subtype_2,\n timestamp: raw.incident_timestamp,\n },\n };\n}\n\n"],"names":[],"mappings":"AAYA,SAAS,YAAY,OAAwD;AACzE,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,IAAI;AACvD,WAAO;AAAA,EACX;AACA,QAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,SAAS,OAAO,EAAE;AAClE,SAAO,MAAM,GAAG,IAAI,SAAY;AACpC;AAKO,SAAS,oBAAoB,KAA4C;AAC5E,SAAO;AAAA,IACH,YAAY,IAAI;AAAA,IAChB,QAAQ,YAAY,IAAI,OAAO;AAAA,IAC/B,WAAW,YAAY,IAAI,YAAY;AAAA,IACvC,MAAM,IAAI;AAAA,IACV,SAAS,IAAI;AAAA,IACb,MAAM;AAAA,MACF,MAAM,IAAI;AAAA,MACV,gBAAgB,IAAI;AAAA,MACpB,UAAU,IAAI;AAAA,MACd,UAAU,IAAI;AAAA,MACd,WAAW,IAAI;AAAA,IAAA;AAAA,EACnB;AAER;"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { transformEvent } from "./match-event.js";
|
|
2
|
+
import { toProviderRefArray } from "../../../shared/providerRef.helper.js";
|
|
3
|
+
function transformLineupPlayer(raw) {
|
|
4
|
+
const player = raw.player;
|
|
5
|
+
return {
|
|
6
|
+
id: player.id,
|
|
7
|
+
name: player.name,
|
|
8
|
+
slug: player.slug,
|
|
9
|
+
position: player.position,
|
|
10
|
+
shirtNumber: raw.shirt_number,
|
|
11
|
+
positionX: raw.position_x ?? void 0,
|
|
12
|
+
positionY: raw.position_y ?? void 0,
|
|
13
|
+
country: player.country ? {
|
|
14
|
+
id: player.country.id,
|
|
15
|
+
name: player.country.name,
|
|
16
|
+
code: player.country.code,
|
|
17
|
+
providerRef: toProviderRefArray(player.country.uuid)
|
|
18
|
+
} : void 0,
|
|
19
|
+
birthdate: player.birthdate,
|
|
20
|
+
profile: player.profile ? {
|
|
21
|
+
height: player.profile.height,
|
|
22
|
+
weight: player.profile.weight
|
|
23
|
+
} : void 0,
|
|
24
|
+
assets: player.assets ? {
|
|
25
|
+
photo: player.assets.thumb?.url,
|
|
26
|
+
photoTransparent: player.assets.thumb_transparent_background?.url
|
|
27
|
+
} : void 0,
|
|
28
|
+
events: raw.events?.map(transformEvent).filter((e) => e !== null),
|
|
29
|
+
providerRef: toProviderRefArray(player.uuid)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function transformCompetitorLineup(raw) {
|
|
33
|
+
const starters = [];
|
|
34
|
+
const substitutes = [];
|
|
35
|
+
for (const entry of raw.players) {
|
|
36
|
+
const player = transformLineupPlayer(entry);
|
|
37
|
+
if (entry.type.category === "start") {
|
|
38
|
+
starters.push(player);
|
|
39
|
+
} else if (entry.type.category === "sub") {
|
|
40
|
+
substitutes.push(player);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
competitorId: raw.team_id,
|
|
45
|
+
formation: raw.formation,
|
|
46
|
+
coach: raw.coach ? {
|
|
47
|
+
id: raw.coach.id,
|
|
48
|
+
name: raw.coach.name,
|
|
49
|
+
slug: raw.coach.slug,
|
|
50
|
+
country: raw.coach.country ? {
|
|
51
|
+
id: raw.coach.country.id,
|
|
52
|
+
name: raw.coach.country.name,
|
|
53
|
+
code: raw.coach.country.code,
|
|
54
|
+
providerRef: toProviderRefArray(raw.coach.country.uuid)
|
|
55
|
+
} : void 0,
|
|
56
|
+
birthdate: raw.coach.birthdate,
|
|
57
|
+
providerRef: toProviderRefArray(raw.coach.uuid)
|
|
58
|
+
} : void 0,
|
|
59
|
+
starters,
|
|
60
|
+
substitutes
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function transformLineups(raw) {
|
|
64
|
+
return {
|
|
65
|
+
matchId: raw.match_id,
|
|
66
|
+
confirmed: raw.status === "CONFIRMED",
|
|
67
|
+
competitorOne: transformCompetitorLineup(raw.home_team),
|
|
68
|
+
competitorTwo: transformCompetitorLineup(raw.away_team)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
transformLineups
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=lineup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineup.js","sources":["../../../../../../src/lib/api/sportal365-sports/football/matches/transformers/lineup.ts"],"sourcesContent":["/**\n * Lineup transformation utilities\n * Transforms raw API lineup responses to canonical FUSports types\n */\n\nimport type {\n FUSportsMatchLineups,\n FUSportsCompetitorLineup,\n FUSportsLineupMember,\n FUSportsMatchEvent,\n} from \"../../../../../types/canonical\";\nimport type { RawMatchLineups, RawTeamLineup, RawLineupPlayerEntry } from \"../types\";\nimport { transformEvent } from \"./match-event\";\nimport { toProviderRefArray } from \"../../../shared\";\n\n/**\n * Transform raw lineup player entry to canonical format\n */\nfunction transformLineupPlayer(raw: RawLineupPlayerEntry): FUSportsLineupMember {\n const player = raw.player;\n return {\n id: player.id,\n name: player.name,\n slug: player.slug,\n position: player.position,\n shirtNumber: raw.shirt_number,\n positionX: raw.position_x ?? undefined,\n positionY: raw.position_y ?? undefined,\n country: player.country\n ? {\n id: player.country.id,\n name: player.country.name,\n code: player.country.code,\n providerRef: toProviderRefArray(player.country.uuid),\n }\n : undefined,\n birthdate: player.birthdate,\n profile: player.profile\n ? {\n height: player.profile.height,\n weight: player.profile.weight,\n }\n : undefined,\n assets: player.assets\n ? {\n photo: player.assets.thumb?.url,\n photoTransparent: player.assets.thumb_transparent_background?.url,\n }\n : undefined,\n events: raw.events?.map(transformEvent).filter((e): e is FUSportsMatchEvent => e !== null),\n providerRef: toProviderRefArray(player.uuid),\n };\n}\n\n/**\n * Transform raw team lineup to canonical format\n */\nfunction transformCompetitorLineup(raw: RawTeamLineup): FUSportsCompetitorLineup {\n const starters: FUSportsLineupMember[] = [];\n const substitutes: FUSportsLineupMember[] = [];\n\n for (const entry of raw.players) {\n const player = transformLineupPlayer(entry);\n // category: 'start' = starter, 'sub' = substitute, 'miss' = injured/unavailable\n if (entry.type.category === \"start\") {\n starters.push(player);\n } else if (entry.type.category === \"sub\") {\n substitutes.push(player);\n }\n // Skip 'miss' category (injured/unavailable players)\n }\n\n return {\n competitorId: raw.team_id,\n formation: raw.formation,\n coach: raw.coach\n ? {\n id: raw.coach.id,\n name: raw.coach.name,\n slug: raw.coach.slug,\n country: raw.coach.country\n ? {\n id: raw.coach.country.id,\n name: raw.coach.country.name,\n code: raw.coach.country.code,\n providerRef: toProviderRefArray(raw.coach.country.uuid),\n }\n : undefined,\n birthdate: raw.coach.birthdate,\n providerRef: toProviderRefArray(raw.coach.uuid),\n }\n : undefined,\n starters,\n substitutes,\n };\n}\n\n/**\n * Transform raw match lineups to canonical format\n */\nexport function transformLineups(raw: RawMatchLineups): FUSportsMatchLineups {\n return {\n matchId: raw.match_id,\n confirmed: raw.status === \"CONFIRMED\",\n competitorOne: transformCompetitorLineup(raw.home_team),\n competitorTwo: transformCompetitorLineup(raw.away_team),\n };\n}\n"],"names":[],"mappings":";;AAkBA,SAAS,sBAAsB,KAAiD;AAC5E,QAAM,SAAS,IAAI;AACnB,SAAO;AAAA,IACH,IAAI,OAAO;AAAA,IACX,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,IACb,UAAU,OAAO;AAAA,IACjB,aAAa,IAAI;AAAA,IACjB,WAAW,IAAI,cAAc;AAAA,IAC7B,WAAW,IAAI,cAAc;AAAA,IAC7B,SAAS,OAAO,UACV;AAAA,MACI,IAAI,OAAO,QAAQ;AAAA,MACnB,MAAM,OAAO,QAAQ;AAAA,MACrB,MAAM,OAAO,QAAQ;AAAA,MACrB,aAAa,mBAAmB,OAAO,QAAQ,IAAI;AAAA,IAAA,IAEvD;AAAA,IACN,WAAW,OAAO;AAAA,IAClB,SAAS,OAAO,UACV;AAAA,MACI,QAAQ,OAAO,QAAQ;AAAA,MACvB,QAAQ,OAAO,QAAQ;AAAA,IAAA,IAE3B;AAAA,IACN,QAAQ,OAAO,SACT;AAAA,MACI,OAAO,OAAO,OAAO,OAAO;AAAA,MAC5B,kBAAkB,OAAO,OAAO,8BAA8B;AAAA,IAAA,IAElE;AAAA,IACN,QAAQ,IAAI,QAAQ,IAAI,cAAc,EAAE,OAAO,CAAC,MAA+B,MAAM,IAAI;AAAA,IACzF,aAAa,mBAAmB,OAAO,IAAI;AAAA,EAAA;AAEnD;AAKA,SAAS,0BAA0B,KAA8C;AAC7E,QAAM,WAAmC,CAAA;AACzC,QAAM,cAAsC,CAAA;AAE5C,aAAW,SAAS,IAAI,SAAS;AAC7B,UAAM,SAAS,sBAAsB,KAAK;AAE1C,QAAI,MAAM,KAAK,aAAa,SAAS;AACjC,eAAS,KAAK,MAAM;AAAA,IACxB,WAAW,MAAM,KAAK,aAAa,OAAO;AACtC,kBAAY,KAAK,MAAM;AAAA,IAC3B;AAAA,EAEJ;AAEA,SAAO;AAAA,IACH,cAAc,IAAI;AAAA,IAClB,WAAW,IAAI;AAAA,IACf,OAAO,IAAI,QACL;AAAA,MACI,IAAI,IAAI,MAAM;AAAA,MACd,MAAM,IAAI,MAAM;AAAA,MAChB,MAAM,IAAI,MAAM;AAAA,MAChB,SAAS,IAAI,MAAM,UACb;AAAA,QACI,IAAI,IAAI,MAAM,QAAQ;AAAA,QACtB,MAAM,IAAI,MAAM,QAAQ;AAAA,QACxB,MAAM,IAAI,MAAM,QAAQ;AAAA,QACxB,aAAa,mBAAmB,IAAI,MAAM,QAAQ,IAAI;AAAA,MAAA,IAE1D;AAAA,MACN,WAAW,IAAI,MAAM;AAAA,MACrB,aAAa,mBAAmB,IAAI,MAAM,IAAI;AAAA,IAAA,IAElD;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAER;AAKO,SAAS,iBAAiB,KAA4C;AACzE,SAAO;AAAA,IACH,SAAS,IAAI;AAAA,IACb,WAAW,IAAI,WAAW;AAAA,IAC1B,eAAe,0BAA0B,IAAI,SAAS;AAAA,IACtD,eAAe,0BAA0B,IAAI,SAAS;AAAA,EAAA;AAE9D;"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
function transformPlayer(raw) {
|
|
2
|
+
if (!raw) return void 0;
|
|
3
|
+
return {
|
|
4
|
+
id: raw.id,
|
|
5
|
+
name: raw.name,
|
|
6
|
+
slug: raw.slug,
|
|
7
|
+
position: raw.position,
|
|
8
|
+
gender: raw.gender,
|
|
9
|
+
assets: raw.assets ? {
|
|
10
|
+
photo: raw.assets.thumb?.url,
|
|
11
|
+
photoTransparent: raw.assets.thumb_transparent_background?.url
|
|
12
|
+
} : void 0
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const EVENT_TYPE_MAP = {
|
|
16
|
+
// Scoring events
|
|
17
|
+
GOAL: "GOAL",
|
|
18
|
+
PENALTY_GOAL: "PENALTY_GOAL",
|
|
19
|
+
OWN_GOAL: "OWN_GOAL",
|
|
20
|
+
DISALLOWED_GOAL: "DISALLOWED_GOAL",
|
|
21
|
+
PENALTY_SHOOTOUT_SCORED: "PENALTY_SHOOTOUT_SCORED",
|
|
22
|
+
PENALTY_SHOOTOUT_MISSED: "PENALTY_SHOOTOUT_MISSED",
|
|
23
|
+
// Card events
|
|
24
|
+
YELLOW_CARD: "YELLOW_CARD",
|
|
25
|
+
RED_CARD: "RED_CARD",
|
|
26
|
+
YELLOW_RED_CARD: "YELLOW_RED_CARD",
|
|
27
|
+
// Substitution
|
|
28
|
+
SUBSTITUTION: "SUBSTITUTION",
|
|
29
|
+
// Match flow events
|
|
30
|
+
KICKOFF: "KICKOFF",
|
|
31
|
+
HALFTIME: "HALFTIME",
|
|
32
|
+
START_SECOND_HALF: "START_SECOND_HALF",
|
|
33
|
+
FINISHED: "FINISHED",
|
|
34
|
+
INJURY_TIME: "INJURY_TIME",
|
|
35
|
+
// Penalty events
|
|
36
|
+
PENALTY_AWARDED: "PENALTY_AWARDED",
|
|
37
|
+
PENALTY_MISSED: "PENALTY_MISSED",
|
|
38
|
+
PENALTY_SAVED: "PENALTY_SAVED"
|
|
39
|
+
};
|
|
40
|
+
function transformEvent(raw) {
|
|
41
|
+
const type = EVENT_TYPE_MAP[raw.type_code];
|
|
42
|
+
if (!type) {
|
|
43
|
+
console.warn(`Unknown event type: ${raw.type_code}`);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
id: raw.id,
|
|
48
|
+
type,
|
|
49
|
+
competitorPosition: raw.team_position === "HOME" ? "ONE" : "TWO",
|
|
50
|
+
minute: raw.minute,
|
|
51
|
+
injuryMinute: raw.injury_minute,
|
|
52
|
+
primaryPlayer: transformPlayer(raw.primary_player),
|
|
53
|
+
secondaryPlayer: transformPlayer(raw.secondary_player),
|
|
54
|
+
score: raw.score ? { competitorOne: String(raw.score.home), competitorTwo: String(raw.score.away) } : void 0
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
transformEvent
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=match-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-event.js","sources":["../../../../../../src/lib/api/sportal365-sports/football/matches/transformers/match-event.ts"],"sourcesContent":["/**\n * Event transformation utilities\n * Transforms raw API event responses to canonical FUSports types\n */\n\nimport type { FUSportsMatchEvent, FUSportsMatchMember } from \"../../../../../types/canonical\";\nimport type { RawMatchEvent } from \"../types\";\n\n/**\n * Transform raw player to canonical format\n */\nfunction transformPlayer(raw: RawMatchEvent[\"primary_player\"]): FUSportsMatchMember | undefined {\n if (!raw) return undefined;\n\n return {\n id: raw.id,\n name: raw.name,\n slug: raw.slug,\n position: raw.position,\n gender: raw.gender,\n assets: raw.assets\n ? {\n photo: raw.assets.thumb?.url,\n photoTransparent: raw.assets.thumb_transparent_background?.url,\n }\n : undefined,\n };\n}\n\n/**\n * Map of raw API event type codes to canonical event types\n */\nconst EVENT_TYPE_MAP: Record<string, FUSportsMatchEvent[\"type\"]> = {\n // Scoring events\n GOAL: \"GOAL\",\n PENALTY_GOAL: \"PENALTY_GOAL\",\n OWN_GOAL: \"OWN_GOAL\",\n DISALLOWED_GOAL: \"DISALLOWED_GOAL\",\n PENALTY_SHOOTOUT_SCORED: \"PENALTY_SHOOTOUT_SCORED\",\n PENALTY_SHOOTOUT_MISSED: \"PENALTY_SHOOTOUT_MISSED\",\n // Card events\n YELLOW_CARD: \"YELLOW_CARD\",\n RED_CARD: \"RED_CARD\",\n YELLOW_RED_CARD: \"YELLOW_RED_CARD\",\n // Substitution\n SUBSTITUTION: \"SUBSTITUTION\",\n // Match flow events\n KICKOFF: \"KICKOFF\",\n HALFTIME: \"HALFTIME\",\n START_SECOND_HALF: \"START_SECOND_HALF\",\n FINISHED: \"FINISHED\",\n INJURY_TIME: \"INJURY_TIME\",\n // Penalty events\n PENALTY_AWARDED: \"PENALTY_AWARDED\",\n PENALTY_MISSED: \"PENALTY_MISSED\",\n PENALTY_SAVED: \"PENALTY_SAVED\",\n};\n\n/**\n * Transform raw event to canonical format\n * Returns null for unknown event types\n */\nexport function transformEvent(raw: RawMatchEvent): FUSportsMatchEvent | null {\n const type = EVENT_TYPE_MAP[raw.type_code];\n\n if (!type) {\n console.warn(`Unknown event type: ${raw.type_code}`);\n return null;\n }\n\n return {\n id: raw.id,\n type,\n competitorPosition: raw.team_position === \"HOME\" ? \"ONE\" : \"TWO\",\n minute: raw.minute,\n injuryMinute: raw.injury_minute,\n primaryPlayer: transformPlayer(raw.primary_player),\n secondaryPlayer: transformPlayer(raw.secondary_player),\n score: raw.score ? { competitorOne: String(raw.score.home), competitorTwo: String(raw.score.away) } : undefined,\n };\n}\n"],"names":[],"mappings":"AAWA,SAAS,gBAAgB,KAAuE;AAC5F,MAAI,CAAC,IAAK,QAAO;AAEjB,SAAO;AAAA,IACH,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,UAAU,IAAI;AAAA,IACd,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI,SACN;AAAA,MACI,OAAO,IAAI,OAAO,OAAO;AAAA,MACzB,kBAAkB,IAAI,OAAO,8BAA8B;AAAA,IAAA,IAE/D;AAAA,EAAA;AAEd;AAKA,MAAM,iBAA6D;AAAA;AAAA,EAE/D,MAAM;AAAA,EACN,cAAc;AAAA,EACd,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,yBAAyB;AAAA,EACzB,yBAAyB;AAAA;AAAA,EAEzB,aAAa;AAAA,EACb,UAAU;AAAA,EACV,iBAAiB;AAAA;AAAA,EAEjB,cAAc;AAAA;AAAA,EAEd,SAAS;AAAA,EACT,UAAU;AAAA,EACV,mBAAmB;AAAA,EACnB,UAAU;AAAA,EACV,aAAa;AAAA;AAAA,EAEb,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,eAAe;AACnB;AAMO,SAAS,eAAe,KAA+C;AAC1E,QAAM,OAAO,eAAe,IAAI,SAAS;AAEzC,MAAI,CAAC,MAAM;AACP,YAAQ,KAAK,uBAAuB,IAAI,SAAS,EAAE;AACnD,WAAO;AAAA,EACX;AAEA,SAAO;AAAA,IACH,IAAI,IAAI;AAAA,IACR;AAAA,IACA,oBAAoB,IAAI,kBAAkB,SAAS,QAAQ;AAAA,IAC3D,QAAQ,IAAI;AAAA,IACZ,cAAc,IAAI;AAAA,IAClB,eAAe,gBAAgB,IAAI,cAAc;AAAA,IACjD,iBAAiB,gBAAgB,IAAI,gBAAgB;AAAA,IACrD,OAAO,IAAI,QAAQ,EAAE,eAAe,OAAO,IAAI,MAAM,IAAI,GAAG,eAAe,OAAO,IAAI,MAAM,IAAI,MAAM;AAAA,EAAA;AAE9G;"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { transformEvent } from "./match-event.js";
|
|
2
|
+
import { toProviderRefArray } from "../../../shared/providerRef.helper.js";
|
|
3
|
+
function transformStatus(raw) {
|
|
4
|
+
const codeMap = {
|
|
5
|
+
finished_ap: "finished_after_penalties",
|
|
6
|
+
// finished after penalties
|
|
7
|
+
finished_aet: "finished_after_extra_time",
|
|
8
|
+
// finished after extra time
|
|
9
|
+
finished: "finished",
|
|
10
|
+
not_started: "not_started",
|
|
11
|
+
live: "live",
|
|
12
|
+
interrupted: "interrupted",
|
|
13
|
+
cancelled: "cancelled",
|
|
14
|
+
postponed: "postponed",
|
|
15
|
+
abandoned: "abandoned"
|
|
16
|
+
};
|
|
17
|
+
let code;
|
|
18
|
+
if (raw.code && codeMap[raw.code]) {
|
|
19
|
+
code = codeMap[raw.code];
|
|
20
|
+
} else {
|
|
21
|
+
const typeMap = {
|
|
22
|
+
FINISHED: "finished",
|
|
23
|
+
NOT_STARTED: "not_started",
|
|
24
|
+
LIVE: "live",
|
|
25
|
+
INTERRUPTED: "interrupted",
|
|
26
|
+
CANCELLED: "cancelled",
|
|
27
|
+
POSTPONED: "postponed",
|
|
28
|
+
UNKNOWN: "not_started",
|
|
29
|
+
ABANDONED: "abandoned"
|
|
30
|
+
};
|
|
31
|
+
code = typeMap[raw.type] ?? "not_started";
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
code,
|
|
35
|
+
name: raw.name,
|
|
36
|
+
shortName: raw.short_name,
|
|
37
|
+
type: raw.type
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function transformTeam(raw) {
|
|
41
|
+
return {
|
|
42
|
+
id: raw.id,
|
|
43
|
+
name: raw.name,
|
|
44
|
+
shortName: raw.short_name ?? void 0,
|
|
45
|
+
threeLetterCode: raw.three_letter_code,
|
|
46
|
+
slug: raw.slug,
|
|
47
|
+
type: raw.type === "national" ? "national" : "club",
|
|
48
|
+
gender: raw.gender,
|
|
49
|
+
assets: raw.assets ? {
|
|
50
|
+
logo: raw.assets.logo?.url,
|
|
51
|
+
homeKit: raw.assets.home_kit?.url,
|
|
52
|
+
awayKit: raw.assets.away_kit?.url,
|
|
53
|
+
squadImage: raw.assets.squad_image?.url
|
|
54
|
+
} : void 0,
|
|
55
|
+
metadata: raw.shirt_color ? {
|
|
56
|
+
shirtColors: [
|
|
57
|
+
{
|
|
58
|
+
type: "home",
|
|
59
|
+
colorCode: raw.shirt_color
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
} : void 0,
|
|
63
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function transformTiming(raw) {
|
|
67
|
+
return {
|
|
68
|
+
kickoffTime: new Date(raw.kickoff_time),
|
|
69
|
+
currentMinute: raw.minute?.regular_time,
|
|
70
|
+
phaseStartedAt: raw.phase_started_at ? new Date(raw.phase_started_at) : void 0,
|
|
71
|
+
finishedAt: raw.finished_at ? new Date(raw.finished_at) : void 0,
|
|
72
|
+
firstHalfStartedAt: raw.first_half_started_at ? new Date(raw.first_half_started_at) : void 0,
|
|
73
|
+
secondHalfStartedAt: raw.second_half_started_at ? new Date(raw.second_half_started_at) : void 0,
|
|
74
|
+
extraTimeFirstHalfStartedAt: raw.extra_time_first_half_started_at ? new Date(raw.extra_time_first_half_started_at) : void 0,
|
|
75
|
+
extraTimeSecondHalfStartedAt: raw.extra_time_second_half_started_at ? new Date(raw.extra_time_second_half_started_at) : void 0
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function transformScore(rawScore) {
|
|
79
|
+
if (!rawScore) return void 0;
|
|
80
|
+
const toScorePair = (s) => s ? { competitorOne: String(s.home), competitorTwo: String(s.away) } : void 0;
|
|
81
|
+
const mainScore = rawScore.after_extra_time ?? rawScore.regular_time;
|
|
82
|
+
return {
|
|
83
|
+
competitorOne: mainScore?.home != null ? String(mainScore.home) : null,
|
|
84
|
+
competitorTwo: mainScore?.away != null ? String(mainScore.away) : null,
|
|
85
|
+
breakdown: {
|
|
86
|
+
total: toScorePair(rawScore.total),
|
|
87
|
+
halfTime: toScorePair(rawScore.half_time),
|
|
88
|
+
regularTime: toScorePair(rawScore.regular_time),
|
|
89
|
+
extraTime: toScorePair(rawScore.extra_time),
|
|
90
|
+
penaltyShootout: toScorePair(rawScore.penalty_shootout),
|
|
91
|
+
aggregate: toScorePair(rawScore.aggregate)
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function transformVenue(raw) {
|
|
96
|
+
if (!raw) return void 0;
|
|
97
|
+
return {
|
|
98
|
+
id: raw.id,
|
|
99
|
+
name: raw.name,
|
|
100
|
+
slug: raw.slug,
|
|
101
|
+
assets: raw.assets?.image?.url ? { image: raw.assets.image.url } : void 0,
|
|
102
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function transformOfficials(referees) {
|
|
106
|
+
if (!referees?.length) return void 0;
|
|
107
|
+
return referees.map((ref) => ({
|
|
108
|
+
id: ref.id,
|
|
109
|
+
name: ref.name,
|
|
110
|
+
slug: ref.slug,
|
|
111
|
+
role: ref.role ?? "REFEREE",
|
|
112
|
+
gender: ref.gender
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
function transformCompetition(raw) {
|
|
116
|
+
if (!raw.season?.tournament) return void 0;
|
|
117
|
+
const { tournament, ...season } = raw.season;
|
|
118
|
+
return {
|
|
119
|
+
id: tournament.id,
|
|
120
|
+
name: tournament.name,
|
|
121
|
+
slug: tournament.slug,
|
|
122
|
+
type: tournament.type,
|
|
123
|
+
region: tournament.region,
|
|
124
|
+
country: tournament.country ? {
|
|
125
|
+
id: tournament.country.id,
|
|
126
|
+
name: tournament.country.name,
|
|
127
|
+
code: tournament.country.code ?? void 0,
|
|
128
|
+
flag: tournament.country.assets?.flag?.url,
|
|
129
|
+
providerRef: toProviderRefArray(tournament.country.uuid)
|
|
130
|
+
} : void 0,
|
|
131
|
+
season: {
|
|
132
|
+
id: season.id,
|
|
133
|
+
name: season.name,
|
|
134
|
+
status: season.status
|
|
135
|
+
},
|
|
136
|
+
stage: raw.stage ? {
|
|
137
|
+
id: raw.stage.id,
|
|
138
|
+
name: raw.stage.name,
|
|
139
|
+
type: raw.stage.type
|
|
140
|
+
} : void 0,
|
|
141
|
+
assets: tournament.assets?.logo?.url ? { logo: tournament.assets.logo.url } : void 0,
|
|
142
|
+
providerRef: toProviderRefArray(tournament.uuid)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function transformWinner(raw) {
|
|
146
|
+
if (!raw.winner?.match?.id) return void 0;
|
|
147
|
+
const reasonMap = {
|
|
148
|
+
"Regular Time": "REGULAR_TIME",
|
|
149
|
+
"Extra Time": "EXTRA_TIME",
|
|
150
|
+
Penalties: "PENALTIES"
|
|
151
|
+
};
|
|
152
|
+
return {
|
|
153
|
+
competitorId: raw.winner.match.id,
|
|
154
|
+
reason: raw.winner.match.reason?.name ? reasonMap[raw.winner.match.reason.name] : void 0,
|
|
155
|
+
aggregate: !!raw.winner.aggregate
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function transformMatch(raw) {
|
|
159
|
+
return {
|
|
160
|
+
id: raw.id,
|
|
161
|
+
slug: raw.slug,
|
|
162
|
+
sport: "football",
|
|
163
|
+
status: transformStatus(raw.status),
|
|
164
|
+
timing: transformTiming(raw),
|
|
165
|
+
competitorOne: transformTeam(raw.home_team),
|
|
166
|
+
competitorTwo: transformTeam(raw.away_team),
|
|
167
|
+
competition: transformCompetition(raw),
|
|
168
|
+
round: raw.round ? {
|
|
169
|
+
id: raw.round.id ?? raw.round.key,
|
|
170
|
+
key: raw.round.key,
|
|
171
|
+
name: raw.round.name,
|
|
172
|
+
type: raw.round.type ?? "REGULAR",
|
|
173
|
+
providerRef: toProviderRefArray(raw.round.uuid)
|
|
174
|
+
} : void 0,
|
|
175
|
+
group: raw.group ? {
|
|
176
|
+
id: raw.group.id,
|
|
177
|
+
name: raw.group.name,
|
|
178
|
+
providerRef: toProviderRefArray(raw.group.uuid)
|
|
179
|
+
} : void 0,
|
|
180
|
+
venue: transformVenue(raw.venue),
|
|
181
|
+
officials: transformOfficials(raw.referees),
|
|
182
|
+
spectators: raw.spectators ?? void 0,
|
|
183
|
+
score: transformScore(raw.score),
|
|
184
|
+
mainEvents: raw.main_events?.map(transformEvent).filter((e) => e !== null),
|
|
185
|
+
penaltyShootoutEvents: raw.penalty_shootout_events?.map(transformEvent).filter((e) => e !== null),
|
|
186
|
+
winner: transformWinner(raw),
|
|
187
|
+
coverage: raw.coverage === "NOT_LIVE" ? "UNKNOWN" : raw.coverage,
|
|
188
|
+
lineupStatus: raw.lineup_status === "UNCONFIRMED" ? "EXPECTED" : raw.lineup_status,
|
|
189
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
transformMatch
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match.js","sources":["../../../../../../src/lib/api/sportal365-sports/football/matches/transformers/match.ts"],"sourcesContent":["/**\n * Match transformation utilities\n * Transforms raw API match responses to canonical FUSports types\n */\n\nimport type {\n FUSportsMatch,\n FUSportsMatchStatus,\n FUSportsMatchTiming,\n FUSportsTeamCompetitor,\n FUSportsCompetition,\n FUSportsVenue,\n FUSportsOfficial,\n FUSportsMatchScore,\n FUSportsMatchWinner,\n FUSportsMatchEvent,\n} from \"../../../../../types/canonical\";\nimport type { RawMatch, RawMatchReferee } from \"../types\";\nimport type { RawScore, RawTeamScore } from \"../../../shared/types\";\nimport { transformEvent } from \"./match-event\";\nimport { toProviderRefArray } from \"../../../shared\";\n\n/**\n * Transform raw match status to canonical format\n */\nfunction transformStatus(raw: RawMatch[\"status\"]): FUSportsMatchStatus {\n // Map raw API status codes to canonical codes\n const codeMap: Record<string, FUSportsMatchStatus[\"code\"]> = {\n finished_ap: \"finished_after_penalties\", // finished after penalties\n finished_aet: \"finished_after_extra_time\", // finished after extra time\n finished: \"finished\",\n not_started: \"not_started\",\n live: \"live\",\n interrupted: \"interrupted\",\n cancelled: \"cancelled\",\n postponed: \"postponed\",\n abandoned: \"abandoned\",\n };\n\n // Use the raw.code if available and mapped, otherwise derive from raw.type\n let code: FUSportsMatchStatus[\"code\"];\n if (raw.code && codeMap[raw.code]) {\n code = codeMap[raw.code];\n } else {\n // Fallback to type-based mapping\n const typeMap: Record<string, FUSportsMatchStatus[\"code\"]> = {\n FINISHED: \"finished\",\n NOT_STARTED: \"not_started\",\n LIVE: \"live\",\n INTERRUPTED: \"interrupted\",\n CANCELLED: \"cancelled\",\n POSTPONED: \"postponed\",\n UNKNOWN: \"not_started\",\n ABANDONED: \"abandoned\",\n };\n code = typeMap[raw.type] ?? \"not_started\";\n }\n\n return {\n code,\n name: raw.name,\n shortName: raw.short_name,\n type: raw.type as FUSportsMatchStatus[\"type\"],\n };\n}\n\n/**\n * Transform raw team to canonical competitor\n */\nfunction transformTeam(raw: RawMatch[\"home_team\"]): FUSportsTeamCompetitor {\n return {\n id: raw.id,\n name: raw.name,\n shortName: raw.short_name ?? undefined,\n threeLetterCode: raw.three_letter_code,\n slug: raw.slug,\n type: (raw.type === \"national\" ? \"national\" : \"club\") as \"club\" | \"national\",\n gender: raw.gender as FUSportsTeamCompetitor[\"gender\"],\n assets: raw.assets\n ? {\n logo: raw.assets.logo?.url,\n homeKit: raw.assets.home_kit?.url,\n awayKit: raw.assets.away_kit?.url,\n squadImage: raw.assets.squad_image?.url,\n }\n : undefined,\n metadata: raw.shirt_color\n ? {\n shirtColors: [\n {\n type: \"home\" as const,\n colorCode: raw.shirt_color,\n },\n ],\n }\n : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw timing fields to canonical timing\n */\nfunction transformTiming(raw: RawMatch): FUSportsMatchTiming {\n return {\n kickoffTime: new Date(raw.kickoff_time),\n currentMinute: raw.minute?.regular_time,\n phaseStartedAt: raw.phase_started_at ? new Date(raw.phase_started_at) : undefined,\n finishedAt: raw.finished_at ? new Date(raw.finished_at) : undefined,\n firstHalfStartedAt: raw.first_half_started_at ? new Date(raw.first_half_started_at) : undefined,\n secondHalfStartedAt: raw.second_half_started_at ? new Date(raw.second_half_started_at) : undefined,\n extraTimeFirstHalfStartedAt: raw.extra_time_first_half_started_at\n ? new Date(raw.extra_time_first_half_started_at)\n : undefined,\n extraTimeSecondHalfStartedAt: raw.extra_time_second_half_started_at\n ? new Date(raw.extra_time_second_half_started_at)\n : undefined,\n };\n}\n\n/**\n * Transform raw score to canonical format\n */\nfunction transformScore(rawScore: RawScore | undefined): FUSportsMatchScore | undefined {\n if (!rawScore) return undefined;\n const toScorePair = (s?: RawTeamScore) =>\n s ? { competitorOne: String(s.home), competitorTwo: String(s.away) } : undefined;\n\n // Use after_extra_time (FT + ET) if available, otherwise fall back to regular_time\n // This ensures the main score doesn't include penalty shootout results\n const mainScore = rawScore.after_extra_time ?? rawScore.regular_time;\n\n return {\n competitorOne: mainScore?.home != null ? String(mainScore.home) : null,\n competitorTwo: mainScore?.away != null ? String(mainScore.away) : null,\n breakdown: {\n total: toScorePair(rawScore.total),\n halfTime: toScorePair(rawScore.half_time),\n regularTime: toScorePair(rawScore.regular_time),\n extraTime: toScorePair(rawScore.extra_time),\n penaltyShootout: toScorePair(rawScore.penalty_shootout),\n aggregate: toScorePair(rawScore.aggregate),\n },\n };\n}\n\n/**\n * Transform raw venue to canonical format\n */\nfunction transformVenue(raw: RawMatch[\"venue\"]): FUSportsVenue | undefined {\n if (!raw) return undefined;\n\n return {\n id: raw.id,\n name: raw.name,\n slug: raw.slug,\n assets: raw.assets?.image?.url ? { image: raw.assets.image.url } : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw referees to canonical officials\n */\nfunction transformOfficials(referees?: RawMatchReferee[]): FUSportsOfficial[] | undefined {\n if (!referees?.length) return undefined;\n\n return referees.map((ref) => ({\n id: ref.id,\n name: ref.name,\n slug: ref.slug,\n role: (ref.role as FUSportsOfficial[\"role\"]) ?? \"REFEREE\",\n gender: ref.gender,\n }));\n}\n\n/**\n * Transform raw competition to canonical format\n */\nfunction transformCompetition(raw: RawMatch): FUSportsCompetition | undefined {\n if (!raw.season?.tournament) return undefined;\n\n const { tournament, ...season } = raw.season;\n\n return {\n id: tournament.id,\n name: tournament.name,\n slug: tournament.slug,\n type: tournament.type as FUSportsCompetition[\"type\"],\n region: tournament.region as FUSportsCompetition[\"region\"],\n country: tournament.country\n ? {\n id: tournament.country.id,\n name: tournament.country.name,\n code: tournament.country.code ?? undefined,\n flag: tournament.country.assets?.flag?.url,\n providerRef: toProviderRefArray(tournament.country.uuid),\n }\n : undefined,\n season: {\n id: season.id,\n name: season.name,\n status: season.status as \"ACTIVE\" | \"INACTIVE\" | \"UPCOMING\",\n },\n stage: raw.stage\n ? {\n id: raw.stage.id,\n name: raw.stage.name,\n type: raw.stage.type,\n }\n : undefined,\n assets: tournament.assets?.logo?.url ? { logo: tournament.assets.logo.url } : undefined,\n providerRef: toProviderRefArray(tournament.uuid),\n };\n}\n\n/**\n * Transform raw winner to canonical format\n */\nfunction transformWinner(raw: RawMatch): FUSportsMatchWinner | undefined {\n if (!raw.winner?.match?.id) return undefined;\n\n const reasonMap: Record<string, FUSportsMatchWinner[\"reason\"]> = {\n \"Regular Time\": \"REGULAR_TIME\",\n \"Extra Time\": \"EXTRA_TIME\",\n Penalties: \"PENALTIES\",\n };\n\n return {\n competitorId: raw.winner.match.id,\n reason: raw.winner.match.reason?.name ? reasonMap[raw.winner.match.reason.name] : undefined,\n aggregate: !!raw.winner.aggregate,\n };\n}\n\n/**\n * Transform raw match response to canonical FUSportsMatch\n */\nexport function transformMatch(raw: RawMatch): FUSportsMatch {\n return {\n id: raw.id,\n slug: raw.slug,\n sport: \"football\",\n status: transformStatus(raw.status),\n timing: transformTiming(raw),\n\n competitorOne: transformTeam(raw.home_team),\n competitorTwo: transformTeam(raw.away_team),\n\n competition: transformCompetition(raw),\n round: raw.round\n ? {\n id: raw.round.id ?? raw.round.key,\n key: raw.round.key,\n name: raw.round.name,\n type: raw.round.type ?? \"REGULAR\",\n providerRef: toProviderRefArray(raw.round.uuid),\n }\n : undefined,\n group: raw.group\n ? {\n id: raw.group.id,\n name: raw.group.name,\n providerRef: toProviderRefArray(raw.group.uuid),\n }\n : undefined,\n\n venue: transformVenue(raw.venue),\n officials: transformOfficials(raw.referees),\n spectators: raw.spectators ?? undefined,\n\n score: transformScore(raw.score),\n\n mainEvents: raw.main_events?.map(transformEvent).filter((e): e is FUSportsMatchEvent => e !== null),\n penaltyShootoutEvents: raw.penalty_shootout_events\n ?.map(transformEvent)\n .filter((e): e is FUSportsMatchEvent => e !== null),\n\n winner: transformWinner(raw),\n\n coverage: raw.coverage === \"NOT_LIVE\" ? \"UNKNOWN\" : raw.coverage,\n lineupStatus:\n raw.lineup_status === \"UNCONFIRMED\" ? \"EXPECTED\" : (raw.lineup_status as FUSportsMatch[\"lineupStatus\"]),\n\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n"],"names":[],"mappings":";;AAyBA,SAAS,gBAAgB,KAA8C;AAEnE,QAAM,UAAuD;AAAA,IACzD,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,UAAU;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,EAAA;AAIf,MAAI;AACJ,MAAI,IAAI,QAAQ,QAAQ,IAAI,IAAI,GAAG;AAC/B,WAAO,QAAQ,IAAI,IAAI;AAAA,EAC3B,OAAO;AAEH,UAAM,UAAuD;AAAA,MACzD,UAAU;AAAA,MACV,aAAa;AAAA,MACb,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS;AAAA,MACT,WAAW;AAAA,IAAA;AAEf,WAAO,QAAQ,IAAI,IAAI,KAAK;AAAA,EAChC;AAEA,SAAO;AAAA,IACH;AAAA,IACA,MAAM,IAAI;AAAA,IACV,WAAW,IAAI;AAAA,IACf,MAAM,IAAI;AAAA,EAAA;AAElB;AAKA,SAAS,cAAc,KAAoD;AACvE,SAAO;AAAA,IACH,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,WAAW,IAAI,cAAc;AAAA,IAC7B,iBAAiB,IAAI;AAAA,IACrB,MAAM,IAAI;AAAA,IACV,MAAO,IAAI,SAAS,aAAa,aAAa;AAAA,IAC9C,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI,SACN;AAAA,MACI,MAAM,IAAI,OAAO,MAAM;AAAA,MACvB,SAAS,IAAI,OAAO,UAAU;AAAA,MAC9B,SAAS,IAAI,OAAO,UAAU;AAAA,MAC9B,YAAY,IAAI,OAAO,aAAa;AAAA,IAAA,IAExC;AAAA,IACN,UAAU,IAAI,cACR;AAAA,MACI,aAAa;AAAA,QACT;AAAA,UACI,MAAM;AAAA,UACN,WAAW,IAAI;AAAA,QAAA;AAAA,MACnB;AAAA,IACJ,IAEJ;AAAA,IACN,aAAa,mBAAmB,IAAI,IAAI;AAAA,EAAA;AAEhD;AAKA,SAAS,gBAAgB,KAAoC;AACzD,SAAO;AAAA,IACH,aAAa,IAAI,KAAK,IAAI,YAAY;AAAA,IACtC,eAAe,IAAI,QAAQ;AAAA,IAC3B,gBAAgB,IAAI,mBAAmB,IAAI,KAAK,IAAI,gBAAgB,IAAI;AAAA,IACxE,YAAY,IAAI,cAAc,IAAI,KAAK,IAAI,WAAW,IAAI;AAAA,IAC1D,oBAAoB,IAAI,wBAAwB,IAAI,KAAK,IAAI,qBAAqB,IAAI;AAAA,IACtF,qBAAqB,IAAI,yBAAyB,IAAI,KAAK,IAAI,sBAAsB,IAAI;AAAA,IACzF,6BAA6B,IAAI,mCAC3B,IAAI,KAAK,IAAI,gCAAgC,IAC7C;AAAA,IACN,8BAA8B,IAAI,oCAC5B,IAAI,KAAK,IAAI,iCAAiC,IAC9C;AAAA,EAAA;AAEd;AAKA,SAAS,eAAe,UAAgE;AACpF,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,cAAc,CAAC,MACjB,IAAI,EAAE,eAAe,OAAO,EAAE,IAAI,GAAG,eAAe,OAAO,EAAE,IAAI,MAAM;AAI3E,QAAM,YAAY,SAAS,oBAAoB,SAAS;AAExD,SAAO;AAAA,IACH,eAAe,WAAW,QAAQ,OAAO,OAAO,UAAU,IAAI,IAAI;AAAA,IAClE,eAAe,WAAW,QAAQ,OAAO,OAAO,UAAU,IAAI,IAAI;AAAA,IAClE,WAAW;AAAA,MACP,OAAO,YAAY,SAAS,KAAK;AAAA,MACjC,UAAU,YAAY,SAAS,SAAS;AAAA,MACxC,aAAa,YAAY,SAAS,YAAY;AAAA,MAC9C,WAAW,YAAY,SAAS,UAAU;AAAA,MAC1C,iBAAiB,YAAY,SAAS,gBAAgB;AAAA,MACtD,WAAW,YAAY,SAAS,SAAS;AAAA,IAAA;AAAA,EAC7C;AAER;AAKA,SAAS,eAAe,KAAmD;AACvE,MAAI,CAAC,IAAK,QAAO;AAEjB,SAAO;AAAA,IACH,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,QAAQ,IAAI,QAAQ,OAAO,MAAM,EAAE,OAAO,IAAI,OAAO,MAAM,IAAA,IAAQ;AAAA,IACnE,aAAa,mBAAmB,IAAI,IAAI;AAAA,EAAA;AAEhD;AAKA,SAAS,mBAAmB,UAA8D;AACtF,MAAI,CAAC,UAAU,OAAQ,QAAO;AAE9B,SAAO,SAAS,IAAI,CAAC,SAAS;AAAA,IAC1B,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,MAAO,IAAI,QAAqC;AAAA,IAChD,QAAQ,IAAI;AAAA,EAAA,EACd;AACN;AAKA,SAAS,qBAAqB,KAAgD;AAC1E,MAAI,CAAC,IAAI,QAAQ,WAAY,QAAO;AAEpC,QAAM,EAAE,YAAY,GAAG,OAAA,IAAW,IAAI;AAEtC,SAAO;AAAA,IACH,IAAI,WAAW;AAAA,IACf,MAAM,WAAW;AAAA,IACjB,MAAM,WAAW;AAAA,IACjB,MAAM,WAAW;AAAA,IACjB,QAAQ,WAAW;AAAA,IACnB,SAAS,WAAW,UACd;AAAA,MACI,IAAI,WAAW,QAAQ;AAAA,MACvB,MAAM,WAAW,QAAQ;AAAA,MACzB,MAAM,WAAW,QAAQ,QAAQ;AAAA,MACjC,MAAM,WAAW,QAAQ,QAAQ,MAAM;AAAA,MACvC,aAAa,mBAAmB,WAAW,QAAQ,IAAI;AAAA,IAAA,IAE3D;AAAA,IACN,QAAQ;AAAA,MACJ,IAAI,OAAO;AAAA,MACX,MAAM,OAAO;AAAA,MACb,QAAQ,OAAO;AAAA,IAAA;AAAA,IAEnB,OAAO,IAAI,QACL;AAAA,MACI,IAAI,IAAI,MAAM;AAAA,MACd,MAAM,IAAI,MAAM;AAAA,MAChB,MAAM,IAAI,MAAM;AAAA,IAAA,IAEpB;AAAA,IACN,QAAQ,WAAW,QAAQ,MAAM,MAAM,EAAE,MAAM,WAAW,OAAO,KAAK,IAAA,IAAQ;AAAA,IAC9E,aAAa,mBAAmB,WAAW,IAAI;AAAA,EAAA;AAEvD;AAKA,SAAS,gBAAgB,KAAgD;AACrE,MAAI,CAAC,IAAI,QAAQ,OAAO,GAAI,QAAO;AAEnC,QAAM,YAA2D;AAAA,IAC7D,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,WAAW;AAAA,EAAA;AAGf,SAAO;AAAA,IACH,cAAc,IAAI,OAAO,MAAM;AAAA,IAC/B,QAAQ,IAAI,OAAO,MAAM,QAAQ,OAAO,UAAU,IAAI,OAAO,MAAM,OAAO,IAAI,IAAI;AAAA,IAClF,WAAW,CAAC,CAAC,IAAI,OAAO;AAAA,EAAA;AAEhC;AAKO,SAAS,eAAe,KAA8B;AACzD,SAAO;AAAA,IACH,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,OAAO;AAAA,IACP,QAAQ,gBAAgB,IAAI,MAAM;AAAA,IAClC,QAAQ,gBAAgB,GAAG;AAAA,IAE3B,eAAe,cAAc,IAAI,SAAS;AAAA,IAC1C,eAAe,cAAc,IAAI,SAAS;AAAA,IAE1C,aAAa,qBAAqB,GAAG;AAAA,IACrC,OAAO,IAAI,QACL;AAAA,MACI,IAAI,IAAI,MAAM,MAAM,IAAI,MAAM;AAAA,MAC9B,KAAK,IAAI,MAAM;AAAA,MACf,MAAM,IAAI,MAAM;AAAA,MAChB,MAAM,IAAI,MAAM,QAAQ;AAAA,MACxB,aAAa,mBAAmB,IAAI,MAAM,IAAI;AAAA,IAAA,IAElD;AAAA,IACN,OAAO,IAAI,QACL;AAAA,MACI,IAAI,IAAI,MAAM;AAAA,MACd,MAAM,IAAI,MAAM;AAAA,MAChB,aAAa,mBAAmB,IAAI,MAAM,IAAI;AAAA,IAAA,IAElD;AAAA,IAEN,OAAO,eAAe,IAAI,KAAK;AAAA,IAC/B,WAAW,mBAAmB,IAAI,QAAQ;AAAA,IAC1C,YAAY,IAAI,cAAc;AAAA,IAE9B,OAAO,eAAe,IAAI,KAAK;AAAA,IAE/B,YAAY,IAAI,aAAa,IAAI,cAAc,EAAE,OAAO,CAAC,MAA+B,MAAM,IAAI;AAAA,IAClG,uBAAuB,IAAI,yBACrB,IAAI,cAAc,EACnB,OAAO,CAAC,MAA+B,MAAM,IAAI;AAAA,IAEtD,QAAQ,gBAAgB,GAAG;AAAA,IAE3B,UAAU,IAAI,aAAa,aAAa,YAAY,IAAI;AAAA,IACxD,cACI,IAAI,kBAAkB,gBAAgB,aAAc,IAAI;AAAA,IAE5D,aAAa,mBAAmB,IAAI,IAAI;AAAA,EAAA;AAEhD;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"odds.js","sources":["../../../../../../src/lib/api/sportal365-sports/football/matches/transformers/odds.ts"],"sourcesContent":["/**\n * Odds transformation utilities\n * Transforms raw API odds responses to canonical FUSports types\n */\n\nimport type { FUSportsMatchOdds } from \"../../../../../types/canonical\";\nimport type { RawMatchOdd } from \"../types\";\nimport { transformOdds } from \"../../../shared\";\n\n/**\n * Transform raw match odds array to canonical format\n */\nexport function transformMatchOdds(matchId: string, raw: RawMatchOdd[]): FUSportsMatchOdds {\n return {\n matchId,\n operators: transformOdds(raw),\n };\n}\n"],"names":[],"mappings":";AAYO,SAAS,mBAAmB,SAAiB,KAAuC;AACvF,SAAO;AAAA,IACH;AAAA,IACA,WAAW,cAAc,GAAG;AAAA,EAAA;AAEpC;"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
function createStatEntry(key, value, label, unit) {
|
|
2
|
+
if (value === void 0 || value === null) return null;
|
|
3
|
+
return { key, value: String(value), label, unit };
|
|
4
|
+
}
|
|
5
|
+
function transformStatisticsData(competitorId, stats) {
|
|
6
|
+
const shotsTotal = (stats.shots_on ?? 0) + (stats.shots_off ?? 0) + (stats.shots_blocked ?? 0);
|
|
7
|
+
const entries = [
|
|
8
|
+
createStatEntry("possession", stats.possession, "Possession", "%"),
|
|
9
|
+
createStatEntry("shots_total", shotsTotal, "Shots"),
|
|
10
|
+
createStatEntry("shots_on_target", stats.shots_on, "Shots on Target"),
|
|
11
|
+
createStatEntry("shots_off_target", stats.shots_off, "Shots off Target"),
|
|
12
|
+
createStatEntry("shots_blocked", stats.shots_blocked, "Shots Blocked"),
|
|
13
|
+
createStatEntry("corners", stats.corners, "Corner Kicks"),
|
|
14
|
+
createStatEntry("goal_kicks", stats.goal_kicks, "Goal Kicks"),
|
|
15
|
+
createStatEntry("throw_ins", stats.throw_in, "Throw Ins"),
|
|
16
|
+
createStatEntry("offsides", stats.offside, "Offsides"),
|
|
17
|
+
createStatEntry("fouls", stats.fouls_committed, "Fouls"),
|
|
18
|
+
createStatEntry("yellow_cards", stats.yellow_cards, "Yellow Cards"),
|
|
19
|
+
createStatEntry("passes", stats.pass, "Passes"),
|
|
20
|
+
createStatEntry("crosses", stats.crosses, "Crosses")
|
|
21
|
+
];
|
|
22
|
+
return {
|
|
23
|
+
competitorId,
|
|
24
|
+
statistics: entries.filter((e) => e !== null)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function transformStatistics(raw) {
|
|
28
|
+
const competitorOneEntry = raw.find((entry) => entry.home_team);
|
|
29
|
+
const competitorTwoEntry = raw.find((entry) => !entry.home_team);
|
|
30
|
+
if (!competitorOneEntry || !competitorTwoEntry) {
|
|
31
|
+
throw new Error("Missing competitor statistics");
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
competitorOne: transformStatisticsData(String(competitorOneEntry.team.id), competitorOneEntry.statistics),
|
|
35
|
+
competitorTwo: transformStatisticsData(String(competitorTwoEntry.team.id), competitorTwoEntry.statistics)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
transformStatistics
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=statistics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statistics.js","sources":["../../../../../../src/lib/api/sportal365-sports/football/matches/transformers/statistics.ts"],"sourcesContent":["/**\n * Statistics transformation utilities\n * Transforms raw API statistics responses to canonical FUSports types\n */\n\nimport type {\n FUSportsMatchStatistics,\n FUSportsCompetitorStatistics,\n FUSportsStatisticEntry,\n} from \"../../../../../types/canonical\";\nimport type { RawMatchStatisticsResponse, RawStatisticsData } from \"../types\";\n\n/**\n * Helper to create a statistic entry if value exists\n */\nfunction createStatEntry(\n key: string,\n value: number | undefined,\n label: string,\n unit?: string\n): FUSportsStatisticEntry | null {\n if (value === undefined || value === null) return null;\n return { key, value: String(value), label, unit };\n}\n\n/**\n * Transform raw statistics data to canonical format\n */\nfunction transformStatisticsData(competitorId: string, stats: RawStatisticsData): FUSportsCompetitorStatistics {\n const shotsTotal = (stats.shots_on ?? 0) + (stats.shots_off ?? 0) + (stats.shots_blocked ?? 0);\n\n const entries: (FUSportsStatisticEntry | null)[] = [\n createStatEntry(\"possession\", stats.possession, \"Possession\", \"%\"),\n createStatEntry(\"shots_total\", shotsTotal, \"Shots\"),\n createStatEntry(\"shots_on_target\", stats.shots_on, \"Shots on Target\"),\n createStatEntry(\"shots_off_target\", stats.shots_off, \"Shots off Target\"),\n createStatEntry(\"shots_blocked\", stats.shots_blocked, \"Shots Blocked\"),\n createStatEntry(\"corners\", stats.corners, \"Corner Kicks\"),\n createStatEntry(\"goal_kicks\", stats.goal_kicks, \"Goal Kicks\"),\n createStatEntry(\"throw_ins\", stats.throw_in, \"Throw Ins\"),\n createStatEntry(\"offsides\", stats.offside, \"Offsides\"),\n createStatEntry(\"fouls\", stats.fouls_committed, \"Fouls\"),\n createStatEntry(\"yellow_cards\", stats.yellow_cards, \"Yellow Cards\"),\n createStatEntry(\"passes\", stats.pass, \"Passes\"),\n createStatEntry(\"crosses\", stats.crosses, \"Crosses\"),\n ];\n\n return {\n competitorId,\n statistics: entries.filter((e): e is FUSportsStatisticEntry => e !== null),\n };\n}\n\n/**\n * Transform raw match statistics response to canonical format\n */\nexport function transformStatistics(raw: RawMatchStatisticsResponse): FUSportsMatchStatistics {\n const competitorOneEntry = raw.find((entry) => entry.home_team);\n const competitorTwoEntry = raw.find((entry) => !entry.home_team);\n\n if (!competitorOneEntry || !competitorTwoEntry) {\n throw new Error(\"Missing competitor statistics\");\n }\n\n return {\n competitorOne: transformStatisticsData(String(competitorOneEntry.team.id), competitorOneEntry.statistics),\n competitorTwo: transformStatisticsData(String(competitorTwoEntry.team.id), competitorTwoEntry.statistics),\n };\n}\n\n"],"names":[],"mappings":"AAeA,SAAS,gBACL,KACA,OACA,OACA,MAC6B;AAC7B,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,SAAO,EAAE,KAAK,OAAO,OAAO,KAAK,GAAG,OAAO,KAAA;AAC/C;AAKA,SAAS,wBAAwB,cAAsB,OAAwD;AAC3G,QAAM,cAAc,MAAM,YAAY,MAAM,MAAM,aAAa,MAAM,MAAM,iBAAiB;AAE5F,QAAM,UAA6C;AAAA,IAC/C,gBAAgB,cAAc,MAAM,YAAY,cAAc,GAAG;AAAA,IACjE,gBAAgB,eAAe,YAAY,OAAO;AAAA,IAClD,gBAAgB,mBAAmB,MAAM,UAAU,iBAAiB;AAAA,IACpE,gBAAgB,oBAAoB,MAAM,WAAW,kBAAkB;AAAA,IACvE,gBAAgB,iBAAiB,MAAM,eAAe,eAAe;AAAA,IACrE,gBAAgB,WAAW,MAAM,SAAS,cAAc;AAAA,IACxD,gBAAgB,cAAc,MAAM,YAAY,YAAY;AAAA,IAC5D,gBAAgB,aAAa,MAAM,UAAU,WAAW;AAAA,IACxD,gBAAgB,YAAY,MAAM,SAAS,UAAU;AAAA,IACrD,gBAAgB,SAAS,MAAM,iBAAiB,OAAO;AAAA,IACvD,gBAAgB,gBAAgB,MAAM,cAAc,cAAc;AAAA,IAClE,gBAAgB,UAAU,MAAM,MAAM,QAAQ;AAAA,IAC9C,gBAAgB,WAAW,MAAM,SAAS,SAAS;AAAA,EAAA;AAGvD,SAAO;AAAA,IACH;AAAA,IACA,YAAY,QAAQ,OAAO,CAAC,MAAmC,MAAM,IAAI;AAAA,EAAA;AAEjF;AAKO,SAAS,oBAAoB,KAA0D;AAC1F,QAAM,qBAAqB,IAAI,KAAK,CAAC,UAAU,MAAM,SAAS;AAC9D,QAAM,qBAAqB,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,SAAS;AAE/D,MAAI,CAAC,sBAAsB,CAAC,oBAAoB;AAC5C,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACnD;AAEA,SAAO;AAAA,IACH,eAAe,wBAAwB,OAAO,mBAAmB,KAAK,EAAE,GAAG,mBAAmB,UAAU;AAAA,IACxG,eAAe,wBAAwB,OAAO,mBAAmB,KAAK,EAAE,GAAG,mBAAmB,UAAU;AAAA,EAAA;AAEhH;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getConfig } from "../../../../config/index.js";
|
|
2
|
+
import { footballHttp } from "../http.js";
|
|
3
|
+
import { transformSearchResult } from "./search.transformer.js";
|
|
4
|
+
async function searchFootball(options, config) {
|
|
5
|
+
if (!options.query || options.query.trim() === "") {
|
|
6
|
+
return {
|
|
7
|
+
results: [],
|
|
8
|
+
query: options.query || ""
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const finalConfig = config || getConfig();
|
|
12
|
+
const { sportal365Sports } = finalConfig;
|
|
13
|
+
const entityTypes = options.entityTypes && options.entityTypes.length > 0 ? options.entityTypes : ["tournament", "player", "team", "president", "venue", "coach"];
|
|
14
|
+
const raw = await footballHttp.get({
|
|
15
|
+
path: "/search",
|
|
16
|
+
params: {
|
|
17
|
+
query: options.query.trim(),
|
|
18
|
+
entity_type: entityTypes.join(","),
|
|
19
|
+
language_code: options.languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
20
|
+
},
|
|
21
|
+
headers: {
|
|
22
|
+
"Accept-Language": options.languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
23
|
+
},
|
|
24
|
+
next: options.next,
|
|
25
|
+
config: finalConfig
|
|
26
|
+
});
|
|
27
|
+
if (!raw || raw.length === 0) {
|
|
28
|
+
return {
|
|
29
|
+
results: [],
|
|
30
|
+
query: options.query
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const results = raw.map(transformSearchResult);
|
|
34
|
+
return {
|
|
35
|
+
results,
|
|
36
|
+
query: options.query
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
searchFootball
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/lib/api/sportal365-sports/football/search/index.ts"],"sourcesContent":["/**\n * Football search endpoints for Sportal365 API\n */\n\nimport type { FUSportsSearchResults } from \"../../../../types/canonical/search.types\";\nimport { getConfig, type DataLayerConfig } from \"../../../../config\";\nimport { footballHttp } from \"../http\";\nimport type { GetFootballSearchOptions, RawSearchResponse } from \"./search.types\";\nimport { transformSearchResult } from \"./search.transformer\";\n\n// Re-export types\nexport type { GetFootballSearchOptions, SearchEntityType } from \"./search.types\";\n\n/**\n * Search for football entities (tournaments, players, teams, presidents, venues, coaches)\n *\n * Returns empty results if no query is provided or no results are found.\n * If no entity types are specified, all types are included in the search.\n *\n * @param options - Search options including query and optional entity types\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Search results with canonical FUSports types\n *\n * @example\n * ```typescript\n * // Search for all entity types\n * const results = await searchFootball({ query: 'lionel' });\n * console.log(`Found ${results.results.length} results`);\n *\n * // Search only for players and teams\n * const results = await searchFootball({\n * query: 'messi',\n * entityTypes: ['player', 'team']\n * });\n *\n * // Handle results by entity type\n * results.results.forEach(result => {\n * switch (result.entityType) {\n * case 'player':\n * console.log(`Player: ${result.name} (${result.position})`);\n * break;\n * case 'team':\n * console.log(`Team: ${result.name} (${result.threeLetterCode})`);\n * break;\n * // ... handle other types\n * }\n * });\n * ```\n */\nexport async function searchFootball(\n options: GetFootballSearchOptions,\n config?: DataLayerConfig\n): Promise<FUSportsSearchResults> {\n // Return empty results if no query is provided\n if (!options.query || options.query.trim() === \"\") {\n return {\n results: [],\n query: options.query || \"\",\n };\n }\n\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n // Build entity_type parameter\n // If no types specified, include all types\n const entityTypes =\n options.entityTypes && options.entityTypes.length > 0\n ? options.entityTypes\n : [\"tournament\", \"player\", \"team\", \"president\", \"venue\", \"coach\"];\n\n const raw = await footballHttp.get<RawSearchResponse>({\n path: \"/search\",\n params: {\n query: options.query.trim(),\n entity_type: entityTypes.join(\",\"),\n language_code: options.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n headers: {\n \"Accept-Language\": options.languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: options.next,\n config: finalConfig,\n });\n\n // Return empty results if no results found\n if (!raw || raw.length === 0) {\n return {\n results: [],\n query: options.query,\n };\n }\n\n // Transform all results\n const results = raw.map(transformSearchResult);\n\n return {\n results,\n query: options.query,\n };\n}\n"],"names":[],"mappings":";;;AAiDA,eAAsB,eAClB,SACA,QAC8B;AAE9B,MAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,KAAA,MAAW,IAAI;AAC/C,WAAO;AAAA,MACH,SAAS,CAAA;AAAA,MACT,OAAO,QAAQ,SAAS;AAAA,IAAA;AAAA,EAEhC;AAEA,QAAM,cAAc,UAAU,UAAA;AAC9B,QAAM,EAAE,qBAAqB;AAI7B,QAAM,cACF,QAAQ,eAAe,QAAQ,YAAY,SAAS,IAC9C,QAAQ,cACR,CAAC,cAAc,UAAU,QAAQ,aAAa,SAAS,OAAO;AAExE,QAAM,MAAM,MAAM,aAAa,IAAuB;AAAA,IAClD,MAAM;AAAA,IACN,QAAQ;AAAA,MACJ,OAAO,QAAQ,MAAM,KAAA;AAAA,MACrB,aAAa,YAAY,KAAK,GAAG;AAAA,MACjC,eAAe,QAAQ,gBAAgB,kBAAkB,gBAAgB;AAAA,IAAA;AAAA,IAE7E,SAAS;AAAA,MACL,mBAAmB,QAAQ,gBAAgB,kBAAkB,gBAAgB;AAAA,IAAA;AAAA,IAEjF,MAAM,QAAQ;AAAA,IACd,QAAQ;AAAA,EAAA,CACX;AAGD,MAAI,CAAC,OAAO,IAAI,WAAW,GAAG;AAC1B,WAAO;AAAA,MACH,SAAS,CAAA;AAAA,MACT,OAAO,QAAQ;AAAA,IAAA;AAAA,EAEvB;AAGA,QAAM,UAAU,IAAI,IAAI,qBAAqB;AAE7C,SAAO;AAAA,IACH;AAAA,IACA,OAAO,QAAQ;AAAA,EAAA;AAEvB;"}
|