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,185 @@
|
|
|
1
|
+
function mapColumnToStat(code) {
|
|
2
|
+
const mapping = {
|
|
3
|
+
RANK: null,
|
|
4
|
+
// rank is a top-level field, not a stat
|
|
5
|
+
PLAYED: "played",
|
|
6
|
+
WINS: "won",
|
|
7
|
+
DRAWS: "drawn",
|
|
8
|
+
LOSSES: "lost",
|
|
9
|
+
GOALS_FOR: "goalsFor",
|
|
10
|
+
GOALS_AGAINST: "goalsAgainst",
|
|
11
|
+
POINTS: "points"
|
|
12
|
+
};
|
|
13
|
+
if (code in mapping) return mapping[code];
|
|
14
|
+
return code.toLowerCase().replace(/_/g, "");
|
|
15
|
+
}
|
|
16
|
+
function mapRuleTypeToKey(ruleType) {
|
|
17
|
+
const mapping = {
|
|
18
|
+
CHAMPIONS_LEAGUE: "championsLeague",
|
|
19
|
+
CHAMPIONS_LEAGUE_QUAL: "championsLeagueQual",
|
|
20
|
+
CHAMPIONS_LEAGUE_8: "championsLeague8",
|
|
21
|
+
CHAMPIONS_LEAGUE_PLAYOFF_16: "championsLeaguePlayoff16",
|
|
22
|
+
PLAYOFF_TO_CHAMPIONS_LEAGUE: "playoffChampionsLeague",
|
|
23
|
+
PLAYOFF_TO_CHAMPIONS_LEAGUE_QUAL: "playoffChampionsLeagueQual",
|
|
24
|
+
UEFA_CUP: "europaLeague",
|
|
25
|
+
UEFA_QUAL: "europaLeagueQual",
|
|
26
|
+
UEFA_QUAL_PLAYOFF: "europaLeagueQualPlayoff",
|
|
27
|
+
PLAYOFF_TO_UEFA_QUAL: "playoffEuropaLeagueQual",
|
|
28
|
+
EUROPA_LEAGUE_8: "europaLeague8",
|
|
29
|
+
EUROPA_LEAGUE_PLAYOFF_16: "europaLeaguePlayoff16",
|
|
30
|
+
EUROPA_CONFERENCE_LEAGUE_PLAYOFF: "europaConferenceLeaguePlayoff",
|
|
31
|
+
EUROPA_CONFERENCE_LEAGUE_QUALIFICATION: "europaConferenceLeagueQual",
|
|
32
|
+
CONFERENCE_LEAGUE_8: "conferenceLeague8",
|
|
33
|
+
CONFERENCE_LEAGUE_PLAYOFF_16: "conferenceLeaguePlayoff16",
|
|
34
|
+
RELEGATION: "relegation",
|
|
35
|
+
RELEGATION_PLAYOFF: "relegationPlayoff",
|
|
36
|
+
PROMOTION: "promotion",
|
|
37
|
+
PROMOTION_PLAYOFF: "promotionPlayoff",
|
|
38
|
+
QUALIFICATION_TO_NEXT_STAGE: "qualificationNextStage",
|
|
39
|
+
POSSIBLE_QUALIFICATION_TO_NEXT_STAGE: "possibleQualificationNextStage",
|
|
40
|
+
CHAMPIONSHIP_PLAYOFF: "championshipPlayoff",
|
|
41
|
+
OVERALL_CHAMPIONSHIP_PLAYOFF: "overallChampionshipPlayoff",
|
|
42
|
+
CONFERENCE_CHAMPIONSHIP_PLAYOFF: "conferenceChampionshipPlayoff",
|
|
43
|
+
POSSIBLE_CONFERENCE_CHAMPIONSHIP_PLAYOFF: "possibleConferenceChampionshipPlayoff",
|
|
44
|
+
DIVISION_CHAMPIONSHIP_PLAYOFF: "divisionChampionshipPlayoff",
|
|
45
|
+
COPA_LIBERTADORES: "copaLibertadores",
|
|
46
|
+
PLAYOFF_TO_COPA_LIBERTADORES: "playoffCopaLibertadores",
|
|
47
|
+
PLAYOFF_TO_COPA_LIBERTADORES_QUAL: "playoffCopaLibertadoresQual",
|
|
48
|
+
PLAYOFF_TO_COPA_SUDAMERICANA: "playoffCopaSudamericana",
|
|
49
|
+
PLAYOFF_TO_CONCACAF_CHAMPIONS_LEAGUE: "playoffConcacafChampionsLeague",
|
|
50
|
+
CAF_CHAMPIONS_QUAL: "cafChampionsQual",
|
|
51
|
+
CAF_CONFEGERATION_CUP_QUAL: "cafConfederationCupQual",
|
|
52
|
+
CFU_CLUB_CHAMPIONSHIP: "cfuClubChampionship",
|
|
53
|
+
AFC_CHAMPIONS_LEAGUE: "afcChampionsLeague",
|
|
54
|
+
AFC_CHAMPIONS_LEAGUE_QUAL: "afcChampionsLeagueQual",
|
|
55
|
+
PLAYOFF_TO_AFC_CHAMPIONS_LEAGUE_QUAL: "playoffAfcChampionsLeagueQual",
|
|
56
|
+
WORLD_CUP: "worldCup"
|
|
57
|
+
};
|
|
58
|
+
return mapping[ruleType] ?? ruleType.toLowerCase().replace(/_/g, "");
|
|
59
|
+
}
|
|
60
|
+
function mapRuleTypeToPosition(ruleType) {
|
|
61
|
+
if (ruleType === "RELEGATION" || ruleType === "RELEGATION_PLAYOFF") return "BOTTOM";
|
|
62
|
+
if (ruleType.includes("PLAYOFF")) return "MIDDLE";
|
|
63
|
+
return "TOP";
|
|
64
|
+
}
|
|
65
|
+
function buildForm(teamId, formMatches) {
|
|
66
|
+
if (!formMatches || formMatches.length === 0) return void 0;
|
|
67
|
+
const outcomeMap = {
|
|
68
|
+
win: "W",
|
|
69
|
+
loss: "L",
|
|
70
|
+
draw: "D"
|
|
71
|
+
};
|
|
72
|
+
const results = formMatches.map((match) => {
|
|
73
|
+
const teamParticipant = match.participants.find((p) => p.id === teamId);
|
|
74
|
+
const opponentParticipant = match.participants.find((p) => p.id !== teamId);
|
|
75
|
+
const isHome = teamParticipant?.position === "1";
|
|
76
|
+
const displayResult = match.result.find((r) => r.type === "display");
|
|
77
|
+
const homeScore = displayResult?.results.find((r) => r.position === "1")?.value;
|
|
78
|
+
const awayScore = displayResult?.results.find((r) => r.position === "2")?.value;
|
|
79
|
+
const score = homeScore && awayScore ? `${homeScore}-${awayScore}` : void 0;
|
|
80
|
+
return {
|
|
81
|
+
matchId: match.id,
|
|
82
|
+
result: outcomeMap[match.outcome] ?? "L",
|
|
83
|
+
score,
|
|
84
|
+
homeAway: isHome ? "HOME" : "AWAY",
|
|
85
|
+
opponent: {
|
|
86
|
+
id: opponentParticipant?.id ?? "",
|
|
87
|
+
name: opponentParticipant?.name ?? "",
|
|
88
|
+
logo: opponentParticipant?.display_asset?.url
|
|
89
|
+
},
|
|
90
|
+
date: new Date(match.start_time),
|
|
91
|
+
competition: match.competition ? {
|
|
92
|
+
id: match.competition.id,
|
|
93
|
+
name: match.competition.name
|
|
94
|
+
} : void 0
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
competitorId: teamId,
|
|
99
|
+
results,
|
|
100
|
+
formString: results.map((r) => r.result).join("")
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function extractStats(columns) {
|
|
104
|
+
const stats = {};
|
|
105
|
+
for (const column of columns) {
|
|
106
|
+
const statKey = mapColumnToStat(column.type.code);
|
|
107
|
+
if (statKey) {
|
|
108
|
+
stats[statKey] = Number(column.value);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (stats.goalsFor != null && stats.goalsAgainst != null && stats.goalDifference == null) {
|
|
112
|
+
stats.goalDifference = stats.goalsFor - stats.goalsAgainst;
|
|
113
|
+
}
|
|
114
|
+
return stats;
|
|
115
|
+
}
|
|
116
|
+
function extractRank(columns) {
|
|
117
|
+
const rankColumn = columns.find((c) => c.type.code === "RANK");
|
|
118
|
+
return rankColumn ? Number(rankColumn.value) : 0;
|
|
119
|
+
}
|
|
120
|
+
function transformEntry(raw) {
|
|
121
|
+
const rules = raw.rules?.length > 0 ? raw.rules.map((r) => mapRuleTypeToKey(r.standing_api_rule_type)) : void 0;
|
|
122
|
+
return {
|
|
123
|
+
rank: extractRank(raw.columns),
|
|
124
|
+
competitor: {
|
|
125
|
+
id: raw.team.id,
|
|
126
|
+
name: raw.team.name,
|
|
127
|
+
shortName: raw.team.short_name ?? void 0,
|
|
128
|
+
logo: void 0
|
|
129
|
+
// Standings API doesn't include logo in team object
|
|
130
|
+
},
|
|
131
|
+
stats: extractStats(raw.columns),
|
|
132
|
+
form: buildForm(raw.team.id, raw.form ?? []),
|
|
133
|
+
rules
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function buildLegend(entries) {
|
|
137
|
+
const legendMap = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const entry of entries) {
|
|
139
|
+
if (entry.rules) {
|
|
140
|
+
for (const rule of entry.rules) {
|
|
141
|
+
const key = mapRuleTypeToKey(rule.standing_api_rule_type);
|
|
142
|
+
if (!legendMap.has(key)) {
|
|
143
|
+
legendMap.set(key, {
|
|
144
|
+
key,
|
|
145
|
+
name: rule.name,
|
|
146
|
+
position: mapRuleTypeToPosition(rule.type)
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return Array.from(legendMap.values());
|
|
153
|
+
}
|
|
154
|
+
function transformGroupStandings(raw) {
|
|
155
|
+
const entries = raw.standing.map(transformEntry);
|
|
156
|
+
const legend = buildLegend(raw.standing);
|
|
157
|
+
return {
|
|
158
|
+
entries,
|
|
159
|
+
metadata: { legend }
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function transformStageData(stageData) {
|
|
163
|
+
return stageData.standings.map((groupStandings) => ({
|
|
164
|
+
stage: {
|
|
165
|
+
id: stageData.stage.id,
|
|
166
|
+
name: stageData.stage.name
|
|
167
|
+
},
|
|
168
|
+
group: {
|
|
169
|
+
id: groupStandings.group.id,
|
|
170
|
+
name: groupStandings.group.name,
|
|
171
|
+
type: groupStandings.group.type
|
|
172
|
+
},
|
|
173
|
+
coverageType: groupStandings.type,
|
|
174
|
+
rankingType: groupStandings.ranking_type,
|
|
175
|
+
standings: transformGroupStandings(groupStandings)
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
function transformStandingsApiResponse(raw) {
|
|
179
|
+
if (!raw?.data || raw.data.length === 0) return [];
|
|
180
|
+
return raw.data.flatMap(transformStageData);
|
|
181
|
+
}
|
|
182
|
+
export {
|
|
183
|
+
transformStandingsApiResponse
|
|
184
|
+
};
|
|
185
|
+
//# sourceMappingURL=standing.transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standing.transformer.js","sources":["../../../../src/lib/api/sportal365-sports/standings/standing.transformer.ts"],"sourcesContent":["/**\n * Standings API Transformer\n * Converts raw Standings API response to canonical FUSports types.\n *\n * Key differences from Football API transformer:\n * - Stats come from key-value columns instead of direct properties\n * - Rules use `standing_api_rule_type` for canonical key mapping\n * - Supports multi-stage / multi-group structures (e.g., World Cup groups, Bulgarian league stages)\n * - Form data uses shared RawFormMatch structure\n */\n\nimport type {\n FUSportsCompetitorForm,\n FUSportsStandingEntry,\n FUSportsStandingLegendItem,\n FUSportsStandings,\n FUSportsStandingsTable,\n} from \"../../../types/canonical\";\nimport type { RawFormMatch } from \"../shared/types\";\nimport type {\n RawStandingsApiColumn,\n RawStandingsApiEntry,\n RawStandingsApiGroupStandings,\n RawStandingsApiResponse,\n RawStandingsApiStageData,\n} from \"./standing.types\";\n\n// ============================================================================\n// Column Code -> Stat Key Mapping\n// ============================================================================\n\n/** Map a column code to a canonical stat key. Returns null for non-stat columns like RANK. */\nfunction mapColumnToStat(code: string): string | null {\n const mapping: Record<string, string | null> = {\n RANK: null, // rank is a top-level field, not a stat\n PLAYED: \"played\",\n WINS: \"won\",\n DRAWS: \"drawn\",\n LOSSES: \"lost\",\n GOALS_FOR: \"goalsFor\",\n GOALS_AGAINST: \"goalsAgainst\",\n POINTS: \"points\",\n };\n\n if (code in mapping) return mapping[code];\n // Unknown columns: lowercase with underscores removed for generic stat access\n return code.toLowerCase().replace(/_/g, \"\");\n}\n\n// ============================================================================\n// Rule Mapping\n// ============================================================================\n\n/** Map standing_api_rule_type to canonical rule key */\nfunction mapRuleTypeToKey(ruleType: string): string {\n const mapping: Record<string, string> = {\n CHAMPIONS_LEAGUE: \"championsLeague\",\n CHAMPIONS_LEAGUE_QUAL: \"championsLeagueQual\",\n CHAMPIONS_LEAGUE_8: \"championsLeague8\",\n CHAMPIONS_LEAGUE_PLAYOFF_16: \"championsLeaguePlayoff16\",\n PLAYOFF_TO_CHAMPIONS_LEAGUE: \"playoffChampionsLeague\",\n PLAYOFF_TO_CHAMPIONS_LEAGUE_QUAL: \"playoffChampionsLeagueQual\",\n UEFA_CUP: \"europaLeague\",\n UEFA_QUAL: \"europaLeagueQual\",\n UEFA_QUAL_PLAYOFF: \"europaLeagueQualPlayoff\",\n PLAYOFF_TO_UEFA_QUAL: \"playoffEuropaLeagueQual\",\n EUROPA_LEAGUE_8: \"europaLeague8\",\n EUROPA_LEAGUE_PLAYOFF_16: \"europaLeaguePlayoff16\",\n EUROPA_CONFERENCE_LEAGUE_PLAYOFF: \"europaConferenceLeaguePlayoff\",\n EUROPA_CONFERENCE_LEAGUE_QUALIFICATION: \"europaConferenceLeagueQual\",\n CONFERENCE_LEAGUE_8: \"conferenceLeague8\",\n CONFERENCE_LEAGUE_PLAYOFF_16: \"conferenceLeaguePlayoff16\",\n RELEGATION: \"relegation\",\n RELEGATION_PLAYOFF: \"relegationPlayoff\",\n PROMOTION: \"promotion\",\n PROMOTION_PLAYOFF: \"promotionPlayoff\",\n QUALIFICATION_TO_NEXT_STAGE: \"qualificationNextStage\",\n POSSIBLE_QUALIFICATION_TO_NEXT_STAGE: \"possibleQualificationNextStage\",\n CHAMPIONSHIP_PLAYOFF: \"championshipPlayoff\",\n OVERALL_CHAMPIONSHIP_PLAYOFF: \"overallChampionshipPlayoff\",\n CONFERENCE_CHAMPIONSHIP_PLAYOFF: \"conferenceChampionshipPlayoff\",\n POSSIBLE_CONFERENCE_CHAMPIONSHIP_PLAYOFF: \"possibleConferenceChampionshipPlayoff\",\n DIVISION_CHAMPIONSHIP_PLAYOFF: \"divisionChampionshipPlayoff\",\n COPA_LIBERTADORES: \"copaLibertadores\",\n PLAYOFF_TO_COPA_LIBERTADORES: \"playoffCopaLibertadores\",\n PLAYOFF_TO_COPA_LIBERTADORES_QUAL: \"playoffCopaLibertadoresQual\",\n PLAYOFF_TO_COPA_SUDAMERICANA: \"playoffCopaSudamericana\",\n PLAYOFF_TO_CONCACAF_CHAMPIONS_LEAGUE: \"playoffConcacafChampionsLeague\",\n CAF_CHAMPIONS_QUAL: \"cafChampionsQual\",\n CAF_CONFEGERATION_CUP_QUAL: \"cafConfederationCupQual\",\n CFU_CLUB_CHAMPIONSHIP: \"cfuClubChampionship\",\n AFC_CHAMPIONS_LEAGUE: \"afcChampionsLeague\",\n AFC_CHAMPIONS_LEAGUE_QUAL: \"afcChampionsLeagueQual\",\n PLAYOFF_TO_AFC_CHAMPIONS_LEAGUE_QUAL: \"playoffAfcChampionsLeagueQual\",\n WORLD_CUP: \"worldCup\",\n };\n return mapping[ruleType] ?? ruleType.toLowerCase().replace(/_/g, \"\");\n}\n\n/** Map rule type to position (TOP/BOTTOM/MIDDLE) */\nfunction mapRuleTypeToPosition(ruleType: string): \"TOP\" | \"BOTTOM\" | \"MIDDLE\" {\n if (ruleType === \"RELEGATION\" || ruleType === \"RELEGATION_PLAYOFF\") return \"BOTTOM\";\n if (ruleType.includes(\"PLAYOFF\")) return \"MIDDLE\";\n return \"TOP\";\n}\n\n// ============================================================================\n// Form Builder\n// ============================================================================\n\nfunction buildForm(teamId: string, formMatches: RawFormMatch[]): FUSportsCompetitorForm | undefined {\n if (!formMatches || formMatches.length === 0) return undefined;\n\n const outcomeMap: Record<string, \"W\" | \"D\" | \"L\"> = {\n win: \"W\",\n loss: \"L\",\n draw: \"D\",\n };\n\n const results = formMatches.map((match) => {\n const teamParticipant = match.participants.find((p) => p.id === teamId);\n const opponentParticipant = match.participants.find((p) => p.id !== teamId);\n const isHome = teamParticipant?.position === \"1\";\n\n // Extract score from display result\n const displayResult = match.result.find((r) => r.type === \"display\");\n const homeScore = displayResult?.results.find((r) => r.position === \"1\")?.value;\n const awayScore = displayResult?.results.find((r) => r.position === \"2\")?.value;\n const score = homeScore && awayScore ? `${homeScore}-${awayScore}` : undefined;\n\n return {\n matchId: match.id,\n result: outcomeMap[match.outcome] ?? (\"L\" as \"W\" | \"D\" | \"L\"),\n score,\n homeAway: (isHome ? \"HOME\" : \"AWAY\") as \"HOME\" | \"AWAY\",\n opponent: {\n id: opponentParticipant?.id ?? \"\",\n name: opponentParticipant?.name ?? \"\",\n logo: opponentParticipant?.display_asset?.url,\n },\n date: new Date(match.start_time),\n competition: match.competition\n ? {\n id: match.competition.id,\n name: match.competition.name,\n }\n : undefined,\n };\n });\n\n return {\n competitorId: teamId,\n results,\n formString: results.map((r) => r.result).join(\"\"),\n };\n}\n\n// ============================================================================\n// Entry Transformer\n// ============================================================================\n\n/** Extract stats from columns array */\nfunction extractStats(columns: RawStandingsApiColumn[]): FUSportsStandingEntry[\"stats\"] {\n const stats: FUSportsStandingEntry[\"stats\"] = {};\n\n for (const column of columns) {\n const statKey = mapColumnToStat(column.type.code);\n if (statKey) {\n stats[statKey] = Number(column.value);\n }\n }\n\n // Compute goal difference if we have both goals for and against\n if (stats.goalsFor != null && stats.goalsAgainst != null && stats.goalDifference == null) {\n stats.goalDifference = stats.goalsFor - stats.goalsAgainst;\n }\n\n return stats;\n}\n\n/** Extract rank from columns (RANK column) */\nfunction extractRank(columns: RawStandingsApiColumn[]): number {\n const rankColumn = columns.find((c) => c.type.code === \"RANK\");\n return rankColumn ? Number(rankColumn.value) : 0;\n}\n\n/** Transform a single standings entry to canonical format */\nfunction transformEntry(raw: RawStandingsApiEntry): FUSportsStandingEntry {\n const rules = raw.rules?.length > 0 ? raw.rules.map((r) => mapRuleTypeToKey(r.standing_api_rule_type)) : undefined;\n\n return {\n rank: extractRank(raw.columns),\n competitor: {\n id: raw.team.id,\n name: raw.team.name,\n shortName: raw.team.short_name ?? undefined,\n logo: undefined, // Standings API doesn't include logo in team object\n },\n stats: extractStats(raw.columns),\n form: buildForm(raw.team.id, raw.form ?? []),\n rules,\n };\n}\n\n// ============================================================================\n// Legend Builder\n// ============================================================================\n\nfunction buildLegend(entries: RawStandingsApiEntry[]): FUSportsStandingLegendItem[] {\n const legendMap = new Map<string, FUSportsStandingLegendItem>();\n\n for (const entry of entries) {\n if (entry.rules) {\n for (const rule of entry.rules) {\n const key = mapRuleTypeToKey(rule.standing_api_rule_type);\n if (!legendMap.has(key)) {\n legendMap.set(key, {\n key,\n name: rule.name,\n position: mapRuleTypeToPosition(rule.type),\n });\n }\n }\n }\n }\n\n return Array.from(legendMap.values());\n}\n\n// ============================================================================\n// Group Standings Transformer\n// ============================================================================\n\n/** Transform a single group standings block to canonical FUSportsStandings */\nfunction transformGroupStandings(raw: RawStandingsApiGroupStandings): FUSportsStandings {\n const entries = raw.standing.map(transformEntry);\n const legend = buildLegend(raw.standing);\n\n return {\n entries,\n metadata: { legend },\n };\n}\n\n// ============================================================================\n// Top-Level Transformer\n// ============================================================================\n\n/** Transform a stage data block to FUSportsStandingsTable[] */\nfunction transformStageData(stageData: RawStandingsApiStageData): FUSportsStandingsTable[] {\n return stageData.standings.map((groupStandings) => ({\n stage: {\n id: stageData.stage.id,\n name: stageData.stage.name,\n },\n group: {\n id: groupStandings.group.id,\n name: groupStandings.group.name,\n type: groupStandings.group.type,\n },\n coverageType: groupStandings.type,\n rankingType: groupStandings.ranking_type,\n standings: transformGroupStandings(groupStandings),\n }));\n}\n\n/**\n * Transform a full Standings API response to an array of FUSportsStandingsTable.\n * Each table represents one stage + group + coverage type combination.\n */\nexport function transformStandingsApiResponse(raw: RawStandingsApiResponse): FUSportsStandingsTable[] {\n if (!raw?.data || raw.data.length === 0) return [];\n\n return raw.data.flatMap(transformStageData);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sources":["../../../../src/lib/api/sportal365-sports/statistics/http.ts"],"sourcesContent":["/**\n * Statistics HTTP client for Sportal365 API\n */\n\nimport { createHttpClient } from \"../http\";\nimport { SPORTAL365_STATISTICS_DOMAIN } from \"../constants\";\n\n/**\n * HTTP client configured for the Sportal365 Statistics API\n */\nexport const statisticsHttp = createHttpClient(SPORTAL365_STATISTICS_DOMAIN);\n\n"],"names":[],"mappings":";;AAUO,MAAM,iBAAiB,iBAAiB,4BAA4B;"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getConfig } from "../../../config/index.js";
|
|
2
|
+
import { statisticsHttp } from "./http.js";
|
|
3
|
+
import { transformTeamStatistics } from "./team-stats.transformer.js";
|
|
4
|
+
async function getTeamSeasonStatistics(options, config) {
|
|
5
|
+
const finalConfig = config || getConfig();
|
|
6
|
+
const cacheOptions = options.next ?? { revalidate: 600 };
|
|
7
|
+
const raw = await statisticsHttp.get({
|
|
8
|
+
path: "/statistics/aggregate",
|
|
9
|
+
params: {
|
|
10
|
+
participant_ids: options.teamId,
|
|
11
|
+
season_ids: options.seasonId,
|
|
12
|
+
participant_type: "TEAM"
|
|
13
|
+
},
|
|
14
|
+
next: cacheOptions,
|
|
15
|
+
config: finalConfig
|
|
16
|
+
});
|
|
17
|
+
if (!raw.data || raw.data.length === 0) {
|
|
18
|
+
throw new Error(`No statistics found for team ${options.teamId} in season ${options.seasonId}`);
|
|
19
|
+
}
|
|
20
|
+
return transformTeamStatistics(raw.data[0], options.seasonId);
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
getTeamSeasonStatistics
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/lib/api/sportal365-sports/statistics/index.ts"],"sourcesContent":["/**\n * Sportal365 Sports API - Statistics\n *\n * Statistics endpoints for the Sportal365 Sports API.\n * All functions return canonical FUSports types.\n */\n\nimport type { FUSportsTeamSeasonStatistics } from \"../../../types/canonical\";\nimport { getConfig, type DataLayerConfig } from \"../../../config\";\nimport type { NextCacheOptions } from \"../http\";\nimport { statisticsHttp } from \"./http\";\nimport type { RawTeamStatisticsResponse } from \"./team-stats.types\";\nimport { transformTeamStatistics } from \"./team-stats.transformer\";\n\n/**\n * Options for getting team season statistics\n */\nexport interface GetTeamSeasonStatisticsOptions {\n /** Team ID (participant ID) - required */\n teamId: string;\n /** Season ID - required */\n seasonId: string;\n /** Next.js cache options for ISR/on-demand revalidation */\n next?: NextCacheOptions;\n}\n\n/**\n * Get team season statistics\n *\n * Fetches aggregate statistics for a team in a specific season.\n * Returns detailed statistics including goals, assists, shots, possession, etc.\n *\n * By default, results are cached for 10 minutes (600 seconds).\n * You can override this by passing a custom `next` option.\n *\n * @param options - Required parameters (teamId, seasonId)\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Canonical FUSportsTeamSeasonStatistics\n *\n * @example\n * ```typescript\n * const stats = await getTeamSeasonStatistics({\n * teamId: '07810505-bdad-4099-bb1d-736c87d0b32c',\n * seasonId: 'e69110fd-4dc5-42f2-91ff-52bdd2326a80'\n * });\n * console.log(stats.teamName); // \"Manchester United\"\n * console.log(stats.statistics); // Array of statistics\n * ```\n *\n * @example\n * ```typescript\n * // Custom cache duration (5 minutes)\n * const stats = await getTeamSeasonStatistics({\n * teamId: '07810505-bdad-4099-bb1d-736c87d0b32c',\n * seasonId: 'e69110fd-4dc5-42f2-91ff-52bdd2326a80',\n * next: { revalidate: 300 }\n * });\n * ```\n */\nexport async function getTeamSeasonStatistics(\n options: GetTeamSeasonStatisticsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsTeamSeasonStatistics> {\n const finalConfig = config || getConfig();\n\n // Default cache: 10 minutes\n const cacheOptions = options.next ?? { revalidate: 600 };\n\n const raw = await statisticsHttp.get<RawTeamStatisticsResponse>({\n path: \"/statistics/aggregate\",\n params: {\n participant_ids: options.teamId,\n season_ids: options.seasonId,\n participant_type: \"TEAM\",\n },\n next: cacheOptions,\n config: finalConfig,\n });\n\n // The API returns an array, but we only request one team\n if (!raw.data || raw.data.length === 0) {\n throw new Error(`No statistics found for team ${options.teamId} in season ${options.seasonId}`);\n }\n\n return transformTeamStatistics(raw.data[0], options.seasonId);\n}\n"],"names":[],"mappings":";;;AA2DA,eAAsB,wBAClB,SACA,QACqC;AACrC,QAAM,cAAc,UAAU,UAAA;AAG9B,QAAM,eAAe,QAAQ,QAAQ,EAAE,YAAY,IAAA;AAEnD,QAAM,MAAM,MAAM,eAAe,IAA+B;AAAA,IAC5D,MAAM;AAAA,IACN,QAAQ;AAAA,MACJ,iBAAiB,QAAQ;AAAA,MACzB,YAAY,QAAQ;AAAA,MACpB,kBAAkB;AAAA,IAAA;AAAA,IAEtB,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA,CACX;AAGD,MAAI,CAAC,IAAI,QAAQ,IAAI,KAAK,WAAW,GAAG;AACpC,UAAM,IAAI,MAAM,gCAAgC,QAAQ,MAAM,cAAc,QAAQ,QAAQ,EAAE;AAAA,EAClG;AAEA,SAAO,wBAAwB,IAAI,KAAK,CAAC,GAAG,QAAQ,QAAQ;AAChE;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
function transformTeamStatistics(raw, seasonId) {
|
|
2
|
+
return {
|
|
3
|
+
teamId: raw.id,
|
|
4
|
+
teamName: raw.name,
|
|
5
|
+
seasonId,
|
|
6
|
+
statistics: raw.statistics.map((stat) => ({
|
|
7
|
+
key: stat.id,
|
|
8
|
+
value: stat.value,
|
|
9
|
+
label: stat.name
|
|
10
|
+
}))
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
transformTeamStatistics
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=team-stats.transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-stats.transformer.js","sources":["../../../../src/lib/api/sportal365-sports/statistics/team-stats.transformer.ts"],"sourcesContent":["/**\n * Team statistics transformation utilities\n * Transforms raw API responses to canonical FUSports types\n */\n\nimport type { FUSportsTeamSeasonStatistics } from \"../../../types/canonical\";\nimport type { RawTeamStatistics } from \"./team-stats.types\";\n\n/**\n * Transform raw team statistics to canonical FUSportsTeamSeasonStatistics\n *\n * Note: The API doesn't return seasonId in the response, so it must be provided\n * from the request parameters.\n */\nexport function transformTeamStatistics(raw: RawTeamStatistics, seasonId: string): FUSportsTeamSeasonStatistics {\n return {\n teamId: raw.id,\n teamName: raw.name,\n seasonId,\n statistics: raw.statistics.map((stat) => ({\n key: stat.id,\n value: stat.value,\n label: stat.name,\n })),\n };\n}\n"],"names":[],"mappings":"AAcO,SAAS,wBAAwB,KAAwB,UAAgD;AAC5G,SAAO;AAAA,IACH,QAAQ,IAAI;AAAA,IACZ,UAAU,IAAI;AAAA,IACd;AAAA,IACA,YAAY,IAAI,WAAW,IAAI,CAAC,UAAU;AAAA,MACtC,KAAK,KAAK;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,IAAA,EACd;AAAA,EAAA;AAEV;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sources":["../../../../src/lib/api/sportal365-sports/tennis/http.ts"],"sourcesContent":["/**\n * Tennis HTTP client for Sportal365 API\n */\n\nimport { createHttpClient } from '../http';\nimport { SPORTAL365_TENNIS_DOMAIN } from '../constants';\n\n/**\n * HTTP client configured for the Sportal365 Tennis API\n */\nexport const tennisHttp = createHttpClient(SPORTAL365_TENNIS_DOMAIN);\n\n"],"names":[],"mappings":";;AAUO,MAAM,aAAa,iBAAiB,wBAAwB;"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getConfig } from "../../../../config/index.js";
|
|
2
|
+
import { tennisHttp } from "../http.js";
|
|
3
|
+
import { transformTennisMatch } from "./transformers/match.js";
|
|
4
|
+
async function getTennisLivescore(options, config) {
|
|
5
|
+
const finalConfig = config || getConfig();
|
|
6
|
+
const { sportal365Sports } = finalConfig;
|
|
7
|
+
const raw = await tennisHttp.get({
|
|
8
|
+
path: `/matches/livescore`,
|
|
9
|
+
params: {
|
|
10
|
+
date: options?.date,
|
|
11
|
+
utc_offset: options?.utcOffset?.toString(),
|
|
12
|
+
offset: "0",
|
|
13
|
+
limit: "1000",
|
|
14
|
+
type: options?.type,
|
|
15
|
+
gender: options?.gender,
|
|
16
|
+
status_type: options?.statusType,
|
|
17
|
+
competition_list: options?.competitionList,
|
|
18
|
+
odd_client: options?.oddClient ?? sportal365Sports?.oddClient,
|
|
19
|
+
odd_type: options?.oddType,
|
|
20
|
+
market_types: options?.marketTypes,
|
|
21
|
+
language_code: options?.languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
22
|
+
},
|
|
23
|
+
headers: {
|
|
24
|
+
"Accept-Language": options?.languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
25
|
+
},
|
|
26
|
+
next: options?.next,
|
|
27
|
+
config: finalConfig
|
|
28
|
+
});
|
|
29
|
+
return raw.matches.map(transformTennisMatch);
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
getTennisLivescore
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/lib/api/sportal365-sports/tennis/matches/index.ts"],"sourcesContent":["/**\n * Tennis matches API functions\n */\n\nimport type { FUSportsMatch } from \"../../../../types/canonical\";\nimport type { DataLayerConfig } from \"../../../../config\";\nimport { getConfig } from \"../../../../config\";\nimport { tennisHttp } from \"../http\";\nimport type { RawTennisMatch, GetTennisLivescoreOptions } from \"./types\";\nimport { transformTennisMatch } from \"./transformers/match\";\n\n/**\n * Get tennis livescore data\n *\n * Fetches live and recent tennis matches from the Sportal365 Tennis API.\n * Returns data in canonical FUSportsMatch format.\n *\n * @param options - Optional filters and configuration\n * @param config - Optional data layer configuration\n * @returns Array of tennis matches in canonical format\n *\n * @example\n * ```typescript\n * // Get all live tennis matches\n * const liveMatches = await getTennisLivescore({\n * statusType: ['LIVE']\n * });\n *\n * // Get singles matches for a specific date\n * const matches = await getTennisLivescore({\n * date: '2024-01-15',\n * type: 'SINGLE',\n * gender: 'MALE'\n * });\n * ```\n */\nexport async function getTennisLivescore(\n options?: GetTennisLivescoreOptions,\n config?: DataLayerConfig\n): Promise<FUSportsMatch[]> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const raw = await tennisHttp.get<{ matches: RawTennisMatch[] }>({\n path: `/matches/livescore`,\n params: {\n date: options?.date,\n utc_offset: options?.utcOffset?.toString(),\n offset: \"0\",\n limit: \"1000\",\n type: options?.type,\n gender: options?.gender,\n status_type: options?.statusType,\n competition_list: options?.competitionList,\n odd_client: options?.oddClient ?? sportal365Sports?.oddClient,\n odd_type: options?.oddType,\n market_types: options?.marketTypes,\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.matches.map(transformTennisMatch);\n}\n"],"names":[],"mappings":";;;AAoCA,eAAsB,mBAClB,SACA,QACwB;AACxB,QAAM,cAAc,UAAU,UAAA;AAC9B,QAAM,EAAE,qBAAqB;AAE7B,QAAM,MAAM,MAAM,WAAW,IAAmC;AAAA,IAC5D,MAAM;AAAA,IACN,QAAQ;AAAA,MACJ,MAAM,SAAS;AAAA,MACf,YAAY,SAAS,WAAW,SAAA;AAAA,MAChC,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,MAAM,SAAS;AAAA,MACf,QAAQ,SAAS;AAAA,MACjB,aAAa,SAAS;AAAA,MACtB,kBAAkB,SAAS;AAAA,MAC3B,YAAY,SAAS,aAAa,kBAAkB;AAAA,MACpD,UAAU,SAAS;AAAA,MACnB,cAAc,SAAS;AAAA,MACvB,eAAe,SAAS,gBAAgB,kBAAkB,gBAAgB;AAAA,IAAA;AAAA,IAE9E,SAAS;AAAA,MACL,mBAAmB,SAAS,gBAAgB,kBAAkB,gBAAgB;AAAA,IAAA;AAAA,IAElF,MAAM,SAAS;AAAA,IACf,QAAQ;AAAA,EAAA,CACX;AAED,SAAO,IAAI,QAAQ,IAAI,oBAAoB;AAC/C;"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { transformOdds } from "../../../shared/odds.transformer.js";
|
|
2
|
+
import { toProviderRefArray } from "../../../shared/providerRef.helper.js";
|
|
3
|
+
function transformStatus(raw) {
|
|
4
|
+
const typeMap = {
|
|
5
|
+
FINISHED: "finished",
|
|
6
|
+
NOT_STARTED: "not_started",
|
|
7
|
+
LIVE: "live",
|
|
8
|
+
INTERRUPTED: "interrupted",
|
|
9
|
+
CANCELLED: "cancelled",
|
|
10
|
+
POSTPONED: "postponed"
|
|
11
|
+
};
|
|
12
|
+
const normalizedType = raw.type.toUpperCase();
|
|
13
|
+
return {
|
|
14
|
+
code: typeMap[normalizedType] ?? "not_started",
|
|
15
|
+
name: raw.name,
|
|
16
|
+
shortName: raw.short_name,
|
|
17
|
+
type: normalizedType
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function transformParticipant(raw) {
|
|
21
|
+
if (raw.type === "PLAYER") {
|
|
22
|
+
const player = {
|
|
23
|
+
id: raw.id,
|
|
24
|
+
name: raw.name,
|
|
25
|
+
shortName: raw.short_name,
|
|
26
|
+
threeLetterCode: raw.three_letter_code,
|
|
27
|
+
type: "player",
|
|
28
|
+
country: raw.details?.[0]?.country ? {
|
|
29
|
+
id: raw.details[0].country.id,
|
|
30
|
+
name: raw.details[0].country.name
|
|
31
|
+
} : void 0,
|
|
32
|
+
gender: raw.details?.[0]?.gender
|
|
33
|
+
};
|
|
34
|
+
return player;
|
|
35
|
+
} else if (raw.type === "TEAM_DOUBLE" && raw.details && raw.details.length === 2) {
|
|
36
|
+
const player1 = {
|
|
37
|
+
id: raw.details[0].id,
|
|
38
|
+
name: raw.details[0].name,
|
|
39
|
+
shortName: raw.details[0].short_name,
|
|
40
|
+
threeLetterCode: raw.details[0].three_letter_code,
|
|
41
|
+
type: "player",
|
|
42
|
+
country: raw.details[0].country ? {
|
|
43
|
+
id: raw.details[0].country.id,
|
|
44
|
+
name: raw.details[0].country.name
|
|
45
|
+
} : void 0,
|
|
46
|
+
gender: raw.details[0].gender
|
|
47
|
+
};
|
|
48
|
+
const player2 = {
|
|
49
|
+
id: raw.details[1].id,
|
|
50
|
+
name: raw.details[1].name,
|
|
51
|
+
shortName: raw.details[1].short_name,
|
|
52
|
+
threeLetterCode: raw.details[1].three_letter_code,
|
|
53
|
+
type: "player",
|
|
54
|
+
country: raw.details[1].country ? {
|
|
55
|
+
id: raw.details[1].country.id,
|
|
56
|
+
name: raw.details[1].country.name
|
|
57
|
+
} : void 0,
|
|
58
|
+
gender: raw.details[1].gender
|
|
59
|
+
};
|
|
60
|
+
const pair = {
|
|
61
|
+
id: raw.id,
|
|
62
|
+
name: raw.name,
|
|
63
|
+
shortName: raw.short_name,
|
|
64
|
+
threeLetterCode: raw.three_letter_code,
|
|
65
|
+
type: "pair",
|
|
66
|
+
players: [player1, player2]
|
|
67
|
+
};
|
|
68
|
+
return pair;
|
|
69
|
+
} else {
|
|
70
|
+
const team = {
|
|
71
|
+
id: raw.id,
|
|
72
|
+
name: raw.name,
|
|
73
|
+
shortName: raw.short_name,
|
|
74
|
+
threeLetterCode: raw.three_letter_code,
|
|
75
|
+
type: "national",
|
|
76
|
+
country: raw.details?.[0]?.country ? {
|
|
77
|
+
id: raw.details[0].country.id,
|
|
78
|
+
name: raw.details[0].country.name
|
|
79
|
+
} : void 0,
|
|
80
|
+
gender: raw.details?.[0]?.gender
|
|
81
|
+
};
|
|
82
|
+
return team;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function transformTiming(raw) {
|
|
86
|
+
return {
|
|
87
|
+
kickoffTime: new Date(raw.scheduled_start_time),
|
|
88
|
+
phaseStartedAt: raw.started_at ? new Date(raw.started_at) : void 0,
|
|
89
|
+
finishedAt: raw.finished_at ? new Date(raw.finished_at) : void 0
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function transformCompetition(raw) {
|
|
93
|
+
if (!raw.tournament) return void 0;
|
|
94
|
+
const tournament = raw.tournament;
|
|
95
|
+
return {
|
|
96
|
+
id: tournament.competition?.id ?? tournament.id,
|
|
97
|
+
name: tournament.competition?.name ?? tournament.name,
|
|
98
|
+
slug: tournament.competition?.slug ?? tournament.slug,
|
|
99
|
+
type: "TOURNAMENT",
|
|
100
|
+
gender: tournament.gender,
|
|
101
|
+
region: "INTERNATIONAL",
|
|
102
|
+
country: tournament.country ? {
|
|
103
|
+
id: tournament.country.id,
|
|
104
|
+
name: tournament.country.name
|
|
105
|
+
} : void 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function transformScore(raw) {
|
|
109
|
+
if (!raw.results || raw.results.length === 0) return void 0;
|
|
110
|
+
const setResults = raw.results.filter((r) => /^set\d+$/i.test(r.type.code));
|
|
111
|
+
if (setResults.length === 0) return void 0;
|
|
112
|
+
const periods = [];
|
|
113
|
+
for (const result of setResults) {
|
|
114
|
+
const val1 = result.values.find((v) => v.position === "1");
|
|
115
|
+
const val2 = result.values.find((v) => v.position === "2");
|
|
116
|
+
if (!val1 || !val2 || val1.value == null || val2.value == null) continue;
|
|
117
|
+
periods.push({
|
|
118
|
+
competitorOne: val1.value,
|
|
119
|
+
competitorTwo: val2.value
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (periods.length === 0) return void 0;
|
|
123
|
+
const setsWonResult = raw.results.find((r) => r.type.code === "setswon");
|
|
124
|
+
const setsWonVal1 = setsWonResult?.values.find((v) => v.position === "1");
|
|
125
|
+
const setsWonVal2 = setsWonResult?.values.find((v) => v.position === "2");
|
|
126
|
+
let totalSetsOne;
|
|
127
|
+
let totalSetsTwo;
|
|
128
|
+
if (setsWonVal1?.value != null && setsWonVal2?.value != null) {
|
|
129
|
+
totalSetsOne = parseInt(setsWonVal1.value);
|
|
130
|
+
totalSetsTwo = parseInt(setsWonVal2.value);
|
|
131
|
+
} else {
|
|
132
|
+
totalSetsOne = periods.filter((p) => parseInt(p.competitorOne) > parseInt(p.competitorTwo)).length;
|
|
133
|
+
totalSetsTwo = periods.filter((p) => parseInt(p.competitorTwo) > parseInt(p.competitorOne)).length;
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
competitorOne: String(totalSetsOne),
|
|
137
|
+
competitorTwo: String(totalSetsTwo),
|
|
138
|
+
breakdown: {
|
|
139
|
+
total: {
|
|
140
|
+
competitorOne: String(totalSetsOne),
|
|
141
|
+
competitorTwo: String(totalSetsTwo)
|
|
142
|
+
},
|
|
143
|
+
periods
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function transformWinner(raw) {
|
|
148
|
+
const winner = raw.participants.find((p) => p.winner === "YES");
|
|
149
|
+
if (!winner) return void 0;
|
|
150
|
+
return {
|
|
151
|
+
competitorId: winner.id
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function transformTennisMatch(raw) {
|
|
155
|
+
const participants = raw.participants.sort((a, b) => a.position - b.position);
|
|
156
|
+
return {
|
|
157
|
+
id: raw.id,
|
|
158
|
+
slug: raw.slug,
|
|
159
|
+
sport: "tennis",
|
|
160
|
+
status: transformStatus(raw.status),
|
|
161
|
+
timing: transformTiming(raw),
|
|
162
|
+
competitorOne: transformParticipant(participants[0]),
|
|
163
|
+
competitorTwo: transformParticipant(participants[1]),
|
|
164
|
+
competition: transformCompetition(raw),
|
|
165
|
+
round: raw.round ? {
|
|
166
|
+
id: raw.round.id,
|
|
167
|
+
key: raw.round.uuid,
|
|
168
|
+
name: raw.round.name,
|
|
169
|
+
type: "REGULAR",
|
|
170
|
+
providerRef: toProviderRefArray(raw.round.uuid)
|
|
171
|
+
} : void 0,
|
|
172
|
+
score: transformScore(raw),
|
|
173
|
+
winner: transformWinner(raw),
|
|
174
|
+
odds: raw.odds ? transformOdds(raw.odds) : void 0,
|
|
175
|
+
coverage: raw.coverage?.type === "NOT_LIVE" ? "UNKNOWN" : raw.coverage?.type,
|
|
176
|
+
metadata: {
|
|
177
|
+
matchType: raw.type,
|
|
178
|
+
bestOfSets: raw.best_of_sets,
|
|
179
|
+
surface: raw.tournament?.surface,
|
|
180
|
+
indoorOutdoor: raw.tournament?.indoor_outdoor
|
|
181
|
+
},
|
|
182
|
+
providerRef: [
|
|
183
|
+
{
|
|
184
|
+
provider: "sportal365-tennis",
|
|
185
|
+
id: raw.id
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
export {
|
|
191
|
+
transformTennisMatch
|
|
192
|
+
};
|
|
193
|
+
//# sourceMappingURL=match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match.js","sources":["../../../../../../src/lib/api/sportal365-sports/tennis/matches/transformers/match.ts"],"sourcesContent":["/**\n * Tennis match transformation utilities\n * Transforms raw Tennis API match responses to canonical FUSports types\n */\n\nimport type {\n FUSportsMatch,\n FUSportsMatchStatus,\n FUSportsMatchTiming,\n FUSportsCompetitor,\n FUSportsPlayerCompetitor,\n FUSportsPairCompetitor,\n FUSportsTeamCompetitor,\n FUSportsCompetition,\n FUSportsMatchScore,\n FUSportsMatchWinner,\n} from \"../../../../../types/canonical\";\nimport type { RawTennisMatch, RawTennisParticipant } from \"../types\";\nimport { toProviderRefArray, transformOdds } from \"../../../shared\";\n\n/**\n * Transform raw tennis status to canonical format\n */\nfunction transformStatus(raw: RawTennisMatch[\"status\"]): FUSportsMatchStatus {\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 };\n\n const normalizedType = raw.type.toUpperCase();\n return {\n code: typeMap[normalizedType] ?? \"not_started\",\n name: raw.name,\n shortName: raw.short_name,\n type: normalizedType as FUSportsMatchStatus[\"type\"],\n };\n}\n\n/**\n * Transform raw tennis participant to canonical competitor\n * Tennis can have: individual players, pairs (doubles), or teams\n */\nfunction transformParticipant(raw: RawTennisParticipant): FUSportsCompetitor {\n if (raw.type === \"PLAYER\") {\n // Single player\n const player: FUSportsPlayerCompetitor = {\n id: raw.id,\n name: raw.name,\n shortName: raw.short_name,\n threeLetterCode: raw.three_letter_code,\n type: \"player\",\n country: raw.details?.[0]?.country\n ? {\n id: raw.details[0].country.id,\n name: raw.details[0].country.name,\n }\n : undefined,\n gender: raw.details?.[0]?.gender as FUSportsPlayerCompetitor[\"gender\"],\n };\n return player;\n } else if (raw.type === \"TEAM_DOUBLE\" && raw.details && raw.details.length === 2) {\n // Pair/doubles team\n const player1: FUSportsPlayerCompetitor = {\n id: raw.details[0].id,\n name: raw.details[0].name,\n shortName: raw.details[0].short_name,\n threeLetterCode: raw.details[0].three_letter_code,\n type: \"player\",\n country: raw.details[0].country\n ? {\n id: raw.details[0].country.id,\n name: raw.details[0].country.name,\n }\n : undefined,\n gender: raw.details[0].gender as FUSportsPlayerCompetitor[\"gender\"],\n };\n\n const player2: FUSportsPlayerCompetitor = {\n id: raw.details[1].id,\n name: raw.details[1].name,\n shortName: raw.details[1].short_name,\n threeLetterCode: raw.details[1].three_letter_code,\n type: \"player\",\n country: raw.details[1].country\n ? {\n id: raw.details[1].country.id,\n name: raw.details[1].country.name,\n }\n : undefined,\n gender: raw.details[1].gender as FUSportsPlayerCompetitor[\"gender\"],\n };\n\n const pair: FUSportsPairCompetitor = {\n id: raw.id,\n name: raw.name,\n shortName: raw.short_name,\n threeLetterCode: raw.three_letter_code,\n type: \"pair\",\n players: [player1, player2],\n };\n return pair;\n } else {\n // Team (for team competitions like Davis Cup)\n const team: FUSportsTeamCompetitor = {\n id: raw.id,\n name: raw.name,\n shortName: raw.short_name,\n threeLetterCode: raw.three_letter_code,\n type: \"national\",\n country: raw.details?.[0]?.country\n ? {\n id: raw.details[0].country.id,\n name: raw.details[0].country.name,\n }\n : undefined,\n gender: raw.details?.[0]?.gender as FUSportsTeamCompetitor[\"gender\"],\n };\n return team;\n }\n}\n\n/**\n * Transform raw tennis timing to canonical format\n */\nfunction transformTiming(raw: RawTennisMatch): FUSportsMatchTiming {\n return {\n kickoffTime: new Date(raw.scheduled_start_time),\n phaseStartedAt: raw.started_at ? new Date(raw.started_at) : undefined,\n finishedAt: raw.finished_at ? new Date(raw.finished_at) : undefined,\n };\n}\n\n/**\n * Transform raw tennis competition to canonical format\n */\nfunction transformCompetition(raw: RawTennisMatch): FUSportsCompetition | undefined {\n if (!raw.tournament) return undefined;\n\n const tournament = raw.tournament;\n return {\n id: tournament.competition?.id ?? tournament.id,\n name: tournament.competition?.name ?? tournament.name,\n slug: tournament.competition?.slug ?? tournament.slug,\n type: \"TOURNAMENT\" as const,\n gender: tournament.gender as FUSportsCompetition[\"gender\"],\n region: \"INTERNATIONAL\" as const,\n country: tournament.country\n ? {\n id: tournament.country.id,\n name: tournament.country.name,\n }\n : undefined,\n };\n}\n\n/**\n * Transform raw tennis score to canonical format\n * Tennis scores are an array of sets with games\n */\nfunction transformScore(raw: RawTennisMatch): FUSportsMatchScore | undefined {\n if (!raw.results || raw.results.length === 0) return undefined;\n\n // Individual set entries have codes \"set1\", \"set2\", \"set3\", etc.\n // Other entries: \"gamescore\", \"setswon\", \"runningscore\", \"finalresult\"\n const setResults = raw.results.filter((r) => /^set\\d+$/i.test(r.type.code));\n if (setResults.length === 0) return undefined;\n\n const periods: Array<{ competitorOne: string; competitorTwo: string }> = [];\n\n for (const result of setResults) {\n const val1 = result.values.find((v) => v.position === \"1\");\n const val2 = result.values.find((v) => v.position === \"2\");\n\n if (!val1 || !val2 || val1.value == null || val2.value == null) continue;\n\n periods.push({\n competitorOne: val1.value,\n competitorTwo: val2.value,\n });\n }\n\n if (periods.length === 0) return undefined;\n\n // Use the \"setswon\" entry for the total sets score if available — more reliable than counting\n const setsWonResult = raw.results.find((r) => r.type.code === \"setswon\");\n const setsWonVal1 = setsWonResult?.values.find((v) => v.position === \"1\");\n const setsWonVal2 = setsWonResult?.values.find((v) => v.position === \"2\");\n\n let totalSetsOne: number;\n let totalSetsTwo: number;\n\n if (setsWonVal1?.value != null && setsWonVal2?.value != null) {\n totalSetsOne = parseInt(setsWonVal1.value);\n totalSetsTwo = parseInt(setsWonVal2.value);\n } else {\n // Fallback: count set wins from individual set entries\n totalSetsOne = periods.filter((p) => parseInt(p.competitorOne) > parseInt(p.competitorTwo)).length;\n totalSetsTwo = periods.filter((p) => parseInt(p.competitorTwo) > parseInt(p.competitorOne)).length;\n }\n\n return {\n competitorOne: String(totalSetsOne),\n competitorTwo: String(totalSetsTwo),\n breakdown: {\n total: {\n competitorOne: String(totalSetsOne),\n competitorTwo: String(totalSetsTwo),\n },\n periods,\n },\n };\n}\n\n/**\n * Transform raw tennis winner to canonical format\n */\nfunction transformWinner(raw: RawTennisMatch): FUSportsMatchWinner | undefined {\n const winner = raw.participants.find((p) => p.winner === \"YES\");\n if (!winner) return undefined;\n\n return {\n competitorId: winner.id,\n };\n}\n\n/**\n * Transform raw tennis match response to canonical FUSportsMatch\n */\nexport function transformTennisMatch(raw: RawTennisMatch): FUSportsMatch {\n const participants = raw.participants.sort((a, b) => a.position - b.position);\n\n return {\n id: raw.id,\n slug: raw.slug,\n sport: \"tennis\",\n status: transformStatus(raw.status),\n timing: transformTiming(raw),\n\n competitorOne: transformParticipant(participants[0]),\n competitorTwo: transformParticipant(participants[1]),\n\n competition: transformCompetition(raw),\n round: raw.round\n ? {\n id: raw.round.id,\n key: raw.round.uuid,\n name: raw.round.name,\n type: \"REGULAR\",\n providerRef: toProviderRefArray(raw.round.uuid),\n }\n : undefined,\n\n score: transformScore(raw),\n\n winner: transformWinner(raw),\n\n odds: raw.odds ? transformOdds(raw.odds) : undefined,\n\n coverage: raw.coverage?.type === \"NOT_LIVE\" ? \"UNKNOWN\" : (raw.coverage?.type as FUSportsMatch[\"coverage\"]),\n\n metadata: {\n matchType: raw.type,\n bestOfSets: raw.best_of_sets,\n surface: raw.tournament?.surface,\n indoorOutdoor: raw.tournament?.indoor_outdoor,\n },\n\n providerRef: [\n {\n provider: \"sportal365-tennis\",\n id: raw.id,\n },\n ],\n };\n}\n"],"names":[],"mappings":"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"}
|