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,166 @@
|
|
|
1
|
+
import { toProviderRefArray } from "../../shared/providerRef.helper.js";
|
|
2
|
+
function transformTournament(raw) {
|
|
3
|
+
return {
|
|
4
|
+
entityType: "tournament",
|
|
5
|
+
id: raw.id.toString(),
|
|
6
|
+
name: raw.name,
|
|
7
|
+
slug: raw.slug,
|
|
8
|
+
gender: raw.gender,
|
|
9
|
+
type: raw.type,
|
|
10
|
+
region: raw.region,
|
|
11
|
+
country: {
|
|
12
|
+
id: raw.country.id.toString(),
|
|
13
|
+
name: raw.country.name,
|
|
14
|
+
code: void 0,
|
|
15
|
+
flag: raw.country.url_flag ?? void 0,
|
|
16
|
+
providerRef: toProviderRefArray(raw.country.uuid)
|
|
17
|
+
},
|
|
18
|
+
assets: raw.url_logo ? {
|
|
19
|
+
logo: raw.url_logo
|
|
20
|
+
} : void 0,
|
|
21
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function transformPlayer(raw) {
|
|
25
|
+
return {
|
|
26
|
+
entityType: "player",
|
|
27
|
+
id: raw.id.toString(),
|
|
28
|
+
name: raw.name,
|
|
29
|
+
slug: raw.slug,
|
|
30
|
+
position: raw.position,
|
|
31
|
+
gender: raw.gender,
|
|
32
|
+
birthdate: raw.birthdate,
|
|
33
|
+
country: {
|
|
34
|
+
id: raw.country.id.toString(),
|
|
35
|
+
name: raw.country.name,
|
|
36
|
+
code: void 0,
|
|
37
|
+
flag: raw.country.url_flag ?? void 0,
|
|
38
|
+
providerRef: toProviderRefArray(raw.country.uuid)
|
|
39
|
+
},
|
|
40
|
+
assets: raw.url_thumb ? {
|
|
41
|
+
photo: raw.url_thumb
|
|
42
|
+
} : void 0,
|
|
43
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function transformTeam(raw) {
|
|
47
|
+
return {
|
|
48
|
+
entityType: "team",
|
|
49
|
+
id: raw.id.toString(),
|
|
50
|
+
name: raw.name,
|
|
51
|
+
slug: raw.slug,
|
|
52
|
+
shortName: raw.short_name ?? void 0,
|
|
53
|
+
threeLetterCode: raw.three_letter_code ?? void 0,
|
|
54
|
+
type: raw.type === "national" ? "national" : "club",
|
|
55
|
+
gender: raw.gender,
|
|
56
|
+
country: {
|
|
57
|
+
id: raw.country.id.toString(),
|
|
58
|
+
name: raw.country.name,
|
|
59
|
+
code: void 0,
|
|
60
|
+
flag: raw.country.url_flag ?? void 0,
|
|
61
|
+
providerRef: toProviderRefArray(raw.country.uuid)
|
|
62
|
+
},
|
|
63
|
+
assets: raw.url_logo ? {
|
|
64
|
+
logo: raw.url_logo
|
|
65
|
+
} : void 0,
|
|
66
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function transformPresident(raw) {
|
|
70
|
+
return {
|
|
71
|
+
entityType: "president",
|
|
72
|
+
id: raw.id.toString(),
|
|
73
|
+
name: raw.name,
|
|
74
|
+
slug: raw.slug,
|
|
75
|
+
birthdate: raw.birthdate ?? void 0,
|
|
76
|
+
country: {
|
|
77
|
+
id: raw.country.id.toString(),
|
|
78
|
+
name: raw.country.name,
|
|
79
|
+
code: void 0,
|
|
80
|
+
flag: raw.country.url_flag ?? void 0,
|
|
81
|
+
providerRef: toProviderRefArray(raw.country.uuid)
|
|
82
|
+
},
|
|
83
|
+
assets: raw.url_thumb ? {
|
|
84
|
+
photo: raw.url_thumb
|
|
85
|
+
} : void 0,
|
|
86
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function transformVenue(raw) {
|
|
90
|
+
return {
|
|
91
|
+
entityType: "venue",
|
|
92
|
+
id: raw.id.toString(),
|
|
93
|
+
name: raw.name,
|
|
94
|
+
slug: raw.slug,
|
|
95
|
+
city: {
|
|
96
|
+
id: raw.city.id.toString(),
|
|
97
|
+
name: raw.city.name,
|
|
98
|
+
country: {
|
|
99
|
+
id: raw.city.country.id.toString(),
|
|
100
|
+
name: raw.city.country.name,
|
|
101
|
+
code: void 0,
|
|
102
|
+
flag: raw.city.country.url_flag ?? void 0,
|
|
103
|
+
providerRef: toProviderRefArray(raw.city.country.uuid)
|
|
104
|
+
},
|
|
105
|
+
providerRef: toProviderRefArray(raw.city.uuid)
|
|
106
|
+
},
|
|
107
|
+
country: {
|
|
108
|
+
id: raw.country.id.toString(),
|
|
109
|
+
name: raw.country.name,
|
|
110
|
+
code: void 0,
|
|
111
|
+
flag: raw.country.url_flag ?? void 0,
|
|
112
|
+
providerRef: toProviderRefArray(raw.country.uuid)
|
|
113
|
+
},
|
|
114
|
+
profile: {
|
|
115
|
+
latitude: raw.profile.lat,
|
|
116
|
+
longitude: raw.profile.lng,
|
|
117
|
+
capacity: raw.profile.capacity
|
|
118
|
+
},
|
|
119
|
+
assets: raw.url_thumb ? {
|
|
120
|
+
image: raw.url_thumb
|
|
121
|
+
} : void 0,
|
|
122
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function transformCoach(raw) {
|
|
126
|
+
return {
|
|
127
|
+
entityType: "coach",
|
|
128
|
+
id: raw.id.toString(),
|
|
129
|
+
name: raw.name,
|
|
130
|
+
slug: raw.slug,
|
|
131
|
+
birthdate: raw.birthdate ?? void 0,
|
|
132
|
+
country: {
|
|
133
|
+
id: raw.country.id.toString(),
|
|
134
|
+
name: raw.country.name,
|
|
135
|
+
code: void 0,
|
|
136
|
+
flag: raw.country.url_flag ?? void 0,
|
|
137
|
+
providerRef: toProviderRefArray(raw.country.uuid)
|
|
138
|
+
},
|
|
139
|
+
assets: raw.url_thumb ? {
|
|
140
|
+
photo: raw.url_thumb
|
|
141
|
+
} : void 0,
|
|
142
|
+
providerRef: toProviderRefArray(raw.uuid)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function transformSearchResult(raw) {
|
|
146
|
+
switch (raw.entity_type) {
|
|
147
|
+
case "tournament":
|
|
148
|
+
return transformTournament(raw);
|
|
149
|
+
case "player":
|
|
150
|
+
return transformPlayer(raw);
|
|
151
|
+
case "team":
|
|
152
|
+
return transformTeam(raw);
|
|
153
|
+
case "president":
|
|
154
|
+
return transformPresident(raw);
|
|
155
|
+
case "venue":
|
|
156
|
+
return transformVenue(raw);
|
|
157
|
+
case "coach":
|
|
158
|
+
return transformCoach(raw);
|
|
159
|
+
default:
|
|
160
|
+
throw new Error(`Unknown entity type: ${raw.entity_type}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export {
|
|
164
|
+
transformSearchResult
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=search.transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.transformer.js","sources":["../../../../../src/lib/api/sportal365-sports/football/search/search.transformer.ts"],"sourcesContent":["/**\n * Transform raw search results to canonical FUSports types\n */\n\nimport type {\n FUSportsSearchResult,\n FUSportsTournamentSearchResult,\n FUSportsPlayerSearchResult,\n FUSportsTeamSearchResult,\n FUSportsPresidentSearchResult,\n FUSportsVenueSearchResult,\n FUSportsCoachSearchResult,\n} from \"../../../../types/canonical/search.types\";\nimport type {\n RawSearchResult,\n RawSearchTournament,\n RawSearchPlayer,\n RawSearchTeam,\n RawSearchPresident,\n RawSearchVenue,\n RawSearchCoach,\n} from \"./search.types\";\nimport { toProviderRefArray } from \"../../shared\";\n\n/**\n * Transform raw tournament search result\n */\nfunction transformTournament(raw: RawSearchTournament): FUSportsTournamentSearchResult {\n return {\n entityType: \"tournament\",\n id: raw.id.toString(),\n name: raw.name,\n slug: raw.slug,\n gender: raw.gender,\n type: raw.type,\n region: raw.region,\n country: {\n id: raw.country.id.toString(),\n name: raw.country.name,\n code: undefined,\n flag: raw.country.url_flag ?? undefined,\n providerRef: toProviderRefArray(raw.country.uuid),\n },\n assets: raw.url_logo\n ? {\n logo: raw.url_logo,\n }\n : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw player search result\n */\nfunction transformPlayer(raw: RawSearchPlayer): FUSportsPlayerSearchResult {\n return {\n entityType: \"player\",\n id: raw.id.toString(),\n name: raw.name,\n slug: raw.slug,\n position: raw.position,\n gender: raw.gender,\n birthdate: raw.birthdate,\n country: {\n id: raw.country.id.toString(),\n name: raw.country.name,\n code: undefined,\n flag: raw.country.url_flag ?? undefined,\n providerRef: toProviderRefArray(raw.country.uuid),\n },\n assets: raw.url_thumb\n ? {\n photo: raw.url_thumb,\n }\n : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw team search result\n */\nfunction transformTeam(raw: RawSearchTeam): FUSportsTeamSearchResult {\n return {\n entityType: \"team\",\n id: raw.id.toString(),\n name: raw.name,\n slug: raw.slug,\n shortName: raw.short_name ?? undefined,\n threeLetterCode: raw.three_letter_code ?? undefined,\n type: raw.type === \"national\" ? \"national\" : \"club\",\n gender: raw.gender,\n country: {\n id: raw.country.id.toString(),\n name: raw.country.name,\n code: undefined,\n flag: raw.country.url_flag ?? undefined,\n providerRef: toProviderRefArray(raw.country.uuid),\n },\n assets: raw.url_logo\n ? {\n logo: raw.url_logo,\n }\n : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw president search result\n */\nfunction transformPresident(raw: RawSearchPresident): FUSportsPresidentSearchResult {\n return {\n entityType: \"president\",\n id: raw.id.toString(),\n name: raw.name,\n slug: raw.slug,\n birthdate: raw.birthdate ?? undefined,\n country: {\n id: raw.country.id.toString(),\n name: raw.country.name,\n code: undefined,\n flag: raw.country.url_flag ?? undefined,\n providerRef: toProviderRefArray(raw.country.uuid),\n },\n assets: raw.url_thumb\n ? {\n photo: raw.url_thumb,\n }\n : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw venue search result\n */\nfunction transformVenue(raw: RawSearchVenue): FUSportsVenueSearchResult {\n return {\n entityType: \"venue\",\n id: raw.id.toString(),\n name: raw.name,\n slug: raw.slug,\n city: {\n id: raw.city.id.toString(),\n name: raw.city.name,\n country: {\n id: raw.city.country.id.toString(),\n name: raw.city.country.name,\n code: undefined,\n flag: raw.city.country.url_flag ?? undefined,\n providerRef: toProviderRefArray(raw.city.country.uuid),\n },\n providerRef: toProviderRefArray(raw.city.uuid),\n },\n country: {\n id: raw.country.id.toString(),\n name: raw.country.name,\n code: undefined,\n flag: raw.country.url_flag ?? undefined,\n providerRef: toProviderRefArray(raw.country.uuid),\n },\n profile: {\n latitude: raw.profile.lat,\n longitude: raw.profile.lng,\n capacity: raw.profile.capacity,\n },\n assets: raw.url_thumb\n ? {\n image: raw.url_thumb,\n }\n : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw coach search result\n */\nfunction transformCoach(raw: RawSearchCoach): FUSportsCoachSearchResult {\n return {\n entityType: \"coach\",\n id: raw.id.toString(),\n name: raw.name,\n slug: raw.slug,\n birthdate: raw.birthdate ?? undefined,\n country: {\n id: raw.country.id.toString(),\n name: raw.country.name,\n code: undefined,\n flag: raw.country.url_flag ?? undefined,\n providerRef: toProviderRefArray(raw.country.uuid),\n },\n assets: raw.url_thumb\n ? {\n photo: raw.url_thumb,\n }\n : undefined,\n providerRef: toProviderRefArray(raw.uuid),\n };\n}\n\n/**\n * Transform raw search result to canonical type\n */\nexport function transformSearchResult(raw: RawSearchResult): FUSportsSearchResult {\n switch (raw.entity_type) {\n case \"tournament\":\n return transformTournament(raw);\n case \"player\":\n return transformPlayer(raw);\n case \"team\":\n return transformTeam(raw);\n case \"president\":\n return transformPresident(raw);\n case \"venue\":\n return transformVenue(raw);\n case \"coach\":\n return transformCoach(raw);\n default:\n // This should never happen with proper typing\n throw new Error(`Unknown entity type: ${(raw as RawSearchResult).entity_type}`);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getConfig } from "../../../../config/index.js";
|
|
2
|
+
import { footballHttp } from "../http.js";
|
|
3
|
+
import { transformStandings } from "./standing.transformer.js";
|
|
4
|
+
async function getFootballStandings(options, config) {
|
|
5
|
+
const finalConfig = config || getConfig();
|
|
6
|
+
const { sportal365Sports } = finalConfig;
|
|
7
|
+
const expandParam = options.expand?.join(",");
|
|
8
|
+
const raw = await footballHttp.get({
|
|
9
|
+
path: `/tournaments/seasons/stages/${options.stageId}/standing`,
|
|
10
|
+
params: {
|
|
11
|
+
expand: expandParam,
|
|
12
|
+
language_code: options.languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
13
|
+
},
|
|
14
|
+
headers: {
|
|
15
|
+
"Accept-Language": options.languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
16
|
+
},
|
|
17
|
+
next: options.next,
|
|
18
|
+
config: finalConfig
|
|
19
|
+
});
|
|
20
|
+
if (!raw || raw.length === 0) {
|
|
21
|
+
return { entries: [], metadata: { legend: [] } };
|
|
22
|
+
}
|
|
23
|
+
return transformStandings(raw);
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
getFootballStandings
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/lib/api/sportal365-sports/football/standings/index.ts"],"sourcesContent":["/**\n * Sportal365 Sports API - Football Standings\n *\n * Fetches standings data from the Football API and transforms to canonical FUSports types.\n */\n\nimport type { FUSportsStandings } from \"../../../../types/canonical\";\nimport { getConfig, type DataLayerConfig } from \"../../../../config\";\nimport { footballHttp } from \"../http\";\nimport type { RawFootballStandingsResponse, GetFootballStandingsOptions } from \"./standing.types\";\nimport { transformStandings } from \"./standing.transformer\";\n\n// Re-export types\nexport type {\n RawFootballStandingTeam,\n RawFootballEventStatus,\n RawFootballFormEvent,\n RawFootballFormEntry,\n RawFootballStandingRule,\n RawFootballStandingEntry,\n RawFootballStandingsResponse,\n GetFootballStandingsOptions,\n FootballStandingsExpandOption,\n} from \"./standing.types\";\n\n/**\n * Get football standings for a stage\n *\n * @param options - Options including stageId (required), languageCode, and expand options\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns FUSportsStandings object with entries and metadata (including legend)\n *\n * @example\n * ```typescript\n * // Get all standings with form data\n * const standings = await getFootballStandings({\n * stageId: '8009708',\n * expand: ['rules', 'form.events']\n * });\n *\n * // Get standings in a specific language\n * const standingsBg = await getFootballStandings({\n * stageId: '8009708',\n * languageCode: 'bg'\n * });\n *\n * // Access entries and metadata\n * standings.entries.forEach(entry => {\n * console.log(`${entry.rank}. ${entry.competitor.name} - ${entry.stats.points} pts`);\n * });\n *\n * // Access legend for rules/zones\n * standings.metadata.legend.forEach(item => {\n * console.log(`${item.name} (${item.position})`);\n * });\n * ```\n */\nexport async function getFootballStandings(\n options: GetFootballStandingsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsStandings> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n // Build expand parameter\n const expandParam = options.expand?.join(\",\");\n\n const raw = await footballHttp.get<RawFootballStandingsResponse>({\n path: `/tournaments/seasons/stages/${options.stageId}/standing`,\n params: {\n expand: expandParam,\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 // The response is a direct array of standing entries\n if (!raw || raw.length === 0) {\n return { entries: [], metadata: { legend: [] } };\n }\n\n return transformStandings(raw);\n}\n"],"names":[],"mappings":";;;AAyDA,eAAsB,qBAClB,SACA,QAC0B;AAC1B,QAAM,cAAc,UAAU,UAAA;AAC9B,QAAM,EAAE,qBAAqB;AAG7B,QAAM,cAAc,QAAQ,QAAQ,KAAK,GAAG;AAE5C,QAAM,MAAM,MAAM,aAAa,IAAkC;AAAA,IAC7D,MAAM,+BAA+B,QAAQ,OAAO;AAAA,IACpD,QAAQ;AAAA,MACJ,QAAQ;AAAA,MACR,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,EAAE,SAAS,CAAA,GAAI,UAAU,EAAE,QAAQ,CAAA,IAAG;AAAA,EACjD;AAEA,SAAO,mBAAmB,GAAG;AACjC;"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
function mapRuleCodeToKey(ruleCode) {
|
|
2
|
+
const mapping = {
|
|
3
|
+
championsleague: "championsLeague",
|
|
4
|
+
europaleague: "europaLeague",
|
|
5
|
+
conferenceleague: "conferenceLeague",
|
|
6
|
+
relegation: "relegation",
|
|
7
|
+
playoff: "playoff",
|
|
8
|
+
promotion: "promotion"
|
|
9
|
+
};
|
|
10
|
+
return mapping[ruleCode.toLowerCase()] ?? ruleCode.toLowerCase().replace(/_/g, "");
|
|
11
|
+
}
|
|
12
|
+
function mapRuleTypeToPosition(ruleType) {
|
|
13
|
+
const lowerType = ruleType.toLowerCase();
|
|
14
|
+
if (lowerType === "relegation") return "BOTTOM";
|
|
15
|
+
if (lowerType === "playoff") return "MIDDLE";
|
|
16
|
+
return "TOP";
|
|
17
|
+
}
|
|
18
|
+
function buildForm(teamId, formEntries) {
|
|
19
|
+
if (!formEntries || formEntries.length === 0) {
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
const results = formEntries.map((entry) => {
|
|
23
|
+
const event = entry.event;
|
|
24
|
+
const isHomeTeam = event.home_team.id === teamId;
|
|
25
|
+
const opponent = isHomeTeam ? event.away_team : event.home_team;
|
|
26
|
+
const score = `${event.goal_home}-${event.goal_away}`;
|
|
27
|
+
return {
|
|
28
|
+
matchId: event.id.toString(),
|
|
29
|
+
result: entry.outcome,
|
|
30
|
+
score,
|
|
31
|
+
homeAway: isHomeTeam ? "HOME" : "AWAY",
|
|
32
|
+
opponent: {
|
|
33
|
+
id: opponent.id.toString(),
|
|
34
|
+
name: opponent.name,
|
|
35
|
+
logo: opponent.url_logo
|
|
36
|
+
},
|
|
37
|
+
date: new Date(event.start_time),
|
|
38
|
+
competition: void 0
|
|
39
|
+
// Football API doesn't include competition in form
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
const formString = results.map((r) => r.result).join("");
|
|
43
|
+
return {
|
|
44
|
+
competitorId: teamId.toString(),
|
|
45
|
+
results,
|
|
46
|
+
formString
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function transformRuleToLegendItem(rule) {
|
|
50
|
+
return {
|
|
51
|
+
key: mapRuleCodeToKey(rule.code),
|
|
52
|
+
name: rule.name,
|
|
53
|
+
position: mapRuleTypeToPosition(rule.type)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function transformStandingEntry(raw) {
|
|
57
|
+
const stats = {
|
|
58
|
+
played: raw.played,
|
|
59
|
+
won: raw.wins,
|
|
60
|
+
drawn: raw.draws,
|
|
61
|
+
lost: raw.defeits,
|
|
62
|
+
goalsFor: raw.goals_for,
|
|
63
|
+
goalsAgainst: raw.goals_against,
|
|
64
|
+
goalDifference: raw.goals_for - raw.goals_against,
|
|
65
|
+
points: raw.points
|
|
66
|
+
};
|
|
67
|
+
const rules = raw.rules?.length > 0 ? raw.rules.map((r) => mapRuleCodeToKey(r.code)) : void 0;
|
|
68
|
+
const form = buildForm(raw.team.id, raw.team.form ?? []);
|
|
69
|
+
return {
|
|
70
|
+
rank: raw.rank,
|
|
71
|
+
competitor: {
|
|
72
|
+
id: raw.team.id.toString(),
|
|
73
|
+
name: raw.team.name,
|
|
74
|
+
shortName: raw.team.short_name ?? void 0,
|
|
75
|
+
logo: raw.team.url_logo,
|
|
76
|
+
uuid: raw.team.uuid
|
|
77
|
+
},
|
|
78
|
+
stats,
|
|
79
|
+
form,
|
|
80
|
+
rules
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function transformStandings(rawEntries) {
|
|
84
|
+
const entries = rawEntries.map(transformStandingEntry);
|
|
85
|
+
const legendMap = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const rawEntry of rawEntries) {
|
|
87
|
+
if (rawEntry.rules) {
|
|
88
|
+
for (const rule of rawEntry.rules) {
|
|
89
|
+
const key = mapRuleCodeToKey(rule.code);
|
|
90
|
+
if (!legendMap.has(key)) {
|
|
91
|
+
legendMap.set(key, transformRuleToLegendItem(rule));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
entries,
|
|
98
|
+
metadata: {
|
|
99
|
+
legend: Array.from(legendMap.values())
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export {
|
|
104
|
+
transformStandingEntry,
|
|
105
|
+
transformStandings
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=standing.transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standing.transformer.js","sources":["../../../../../src/lib/api/sportal365-sports/football/standings/standing.transformer.ts"],"sourcesContent":["/**\n * Football API Standings Transformer\n * Converts raw Football API standings to canonical FUSports types\n */\n\nimport type {\n FUSportsCompetitorForm,\n FUSportsStandingEntry,\n FUSportsStandingLegendItem,\n FUSportsStandings,\n} from \"../../../../types/canonical\";\nimport type { RawFootballStandingEntry, RawFootballFormEntry, RawFootballStandingRule } from \"./standing.types\";\n\n/**\n * Map Football API rule code to canonical key\n */\nfunction mapRuleCodeToKey(ruleCode: string): string {\n const mapping: Record<string, string> = {\n championsleague: \"championsLeague\",\n europaleague: \"europaLeague\",\n conferenceleague: \"conferenceLeague\",\n relegation: \"relegation\",\n playoff: \"playoff\",\n promotion: \"promotion\",\n };\n return mapping[ruleCode.toLowerCase()] ?? ruleCode.toLowerCase().replace(/_/g, \"\");\n}\n\n/**\n * Map Football API rule type to position\n */\nfunction mapRuleTypeToPosition(ruleType: string): \"TOP\" | \"BOTTOM\" | \"MIDDLE\" {\n const lowerType = ruleType.toLowerCase();\n if (lowerType === \"relegation\") return \"BOTTOM\";\n if (lowerType === \"playoff\") return \"MIDDLE\";\n return \"TOP\";\n}\n\n/**\n * Build FUSportsCompetitorForm from Football API form entries\n */\nfunction buildForm(teamId: number, formEntries: RawFootballFormEntry[]): FUSportsCompetitorForm | undefined {\n if (!formEntries || formEntries.length === 0) {\n return undefined;\n }\n\n const results = formEntries.map((entry) => {\n const event = entry.event;\n const isHomeTeam = event.home_team.id === teamId;\n const opponent = isHomeTeam ? event.away_team : event.home_team;\n const score = `${event.goal_home}-${event.goal_away}`;\n\n return {\n matchId: event.id.toString(),\n result: entry.outcome,\n score,\n homeAway: (isHomeTeam ? \"HOME\" : \"AWAY\") as \"HOME\" | \"AWAY\",\n opponent: {\n id: opponent.id.toString(),\n name: opponent.name,\n logo: opponent.url_logo,\n },\n date: new Date(event.start_time),\n competition: undefined, // Football API doesn't include competition in form\n };\n });\n\n const formString = results.map((r) => r.result).join(\"\");\n\n return {\n competitorId: teamId.toString(),\n results,\n formString,\n };\n}\n\n/**\n * Transform a Football API rule to a legend item\n */\nfunction transformRuleToLegendItem(rule: RawFootballStandingRule): FUSportsStandingLegendItem {\n return {\n key: mapRuleCodeToKey(rule.code),\n name: rule.name,\n position: mapRuleTypeToPosition(rule.type),\n };\n}\n\n/**\n * Transform a single Football API standing entry to canonical format\n */\nexport function transformStandingEntry(raw: RawFootballStandingEntry): FUSportsStandingEntry {\n // Build stats from direct properties\n const stats: FUSportsStandingEntry[\"stats\"] = {\n played: raw.played,\n won: raw.wins,\n drawn: raw.draws,\n lost: raw.defeits,\n goalsFor: raw.goals_for,\n goalsAgainst: raw.goals_against,\n goalDifference: raw.goals_for - raw.goals_against,\n points: raw.points,\n };\n\n // Build rules array from raw rules\n const rules = raw.rules?.length > 0 ? raw.rules.map((r) => mapRuleCodeToKey(r.code)) : undefined;\n\n // Build form from form entries\n const form = buildForm(raw.team.id, raw.team.form ?? []);\n\n return {\n rank: raw.rank,\n competitor: {\n id: raw.team.id.toString(),\n name: raw.team.name,\n shortName: raw.team.short_name ?? undefined,\n logo: raw.team.url_logo,\n uuid: raw.team.uuid,\n },\n stats,\n form,\n rules,\n };\n}\n\n/**\n * Transform Football API standing entries to canonical standings with legend\n */\nexport function transformStandings(rawEntries: RawFootballStandingEntry[]): FUSportsStandings {\n const entries = rawEntries.map(transformStandingEntry);\n\n // Build legend from all unique rules across entries\n const legendMap = new Map<string, FUSportsStandingLegendItem>();\n\n for (const rawEntry of rawEntries) {\n if (rawEntry.rules) {\n for (const rule of rawEntry.rules) {\n const key = mapRuleCodeToKey(rule.code);\n if (!legendMap.has(key)) {\n legendMap.set(key, transformRuleToLegendItem(rule));\n }\n }\n }\n }\n\n return {\n entries,\n metadata: {\n legend: Array.from(legendMap.values()),\n },\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { getConfig } from "../../../../config/index.js";
|
|
2
|
+
import { footballHttp } from "../http.js";
|
|
3
|
+
import { transformPlayerSeasonStatistics, transformPlayerSeasonStatisticsWithoutTeam, mergePlayerSeasonStatistics } from "./player-season.transformer.js";
|
|
4
|
+
import { transformPlayerCareerStatistics } from "./player-career.transformer.js";
|
|
5
|
+
import { transformPlayerRecentStatistics } from "./player-recent.transformer.js";
|
|
6
|
+
async function getFootballPlayerSeasonStatistics(options, config) {
|
|
7
|
+
const finalConfig = config || getConfig();
|
|
8
|
+
const { sportal365Sports } = finalConfig;
|
|
9
|
+
const { seasonIds, teamId, languageCode, next } = options;
|
|
10
|
+
const cacheOptions = next ?? { revalidate: 0 };
|
|
11
|
+
const params = {
|
|
12
|
+
season_ids: seasonIds.join(","),
|
|
13
|
+
team_id: teamId,
|
|
14
|
+
language_code: languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
15
|
+
};
|
|
16
|
+
const raw = await footballHttp.get({
|
|
17
|
+
path: `/v2/statistics/players/season`,
|
|
18
|
+
params,
|
|
19
|
+
headers: {
|
|
20
|
+
"Accept-Language": languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
21
|
+
},
|
|
22
|
+
next: cacheOptions,
|
|
23
|
+
config: finalConfig
|
|
24
|
+
});
|
|
25
|
+
if (!raw.statistics) {
|
|
26
|
+
console.error("[getFootballPlayerSeasonStatistics] Invalid API response - missing statistics array:", {
|
|
27
|
+
teamId,
|
|
28
|
+
seasonIds,
|
|
29
|
+
response: raw
|
|
30
|
+
});
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
if (raw.statistics.length === 0) {
|
|
34
|
+
console.warn("[getFootballPlayerSeasonStatistics] API returned empty statistics array:", {
|
|
35
|
+
teamId,
|
|
36
|
+
seasonIds,
|
|
37
|
+
hint: "This could be due to: wrong credentials, wrong project header, no data for this team/season, or API issue"
|
|
38
|
+
});
|
|
39
|
+
throw new Error(
|
|
40
|
+
`No player statistics found for team ${teamId} in seasons ${seasonIds.join(", ")}. This could be due to: wrong credentials, wrong X-Project header, or no data available for this team/season.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const result = {};
|
|
44
|
+
for (const entry of raw.statistics) {
|
|
45
|
+
const playerId = entry.player.id;
|
|
46
|
+
result[playerId] = transformPlayerSeasonStatistics(entry, teamId);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
async function getFootballPlayerSeasonStatisticsByPlayerIds(options, config) {
|
|
51
|
+
const finalConfig = config || getConfig();
|
|
52
|
+
const { sportal365Sports } = finalConfig;
|
|
53
|
+
const { playerIds, seasonIds, languageCode, next } = options;
|
|
54
|
+
const cacheOptions = next ?? { revalidate: 0 };
|
|
55
|
+
const params = {
|
|
56
|
+
player_ids: playerIds.join(","),
|
|
57
|
+
season_ids: seasonIds.join(","),
|
|
58
|
+
language_code: languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
59
|
+
};
|
|
60
|
+
const raw = await footballHttp.get({
|
|
61
|
+
path: `/v2/statistics/players/season`,
|
|
62
|
+
params,
|
|
63
|
+
headers: {
|
|
64
|
+
"Accept-Language": languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
65
|
+
},
|
|
66
|
+
next: cacheOptions,
|
|
67
|
+
config: finalConfig
|
|
68
|
+
});
|
|
69
|
+
if (!raw.statistics) {
|
|
70
|
+
console.error("[getFootballPlayerSeasonStatisticsByPlayerIds] Invalid API response - missing statistics array:", {
|
|
71
|
+
playerIds,
|
|
72
|
+
seasonIds,
|
|
73
|
+
response: raw
|
|
74
|
+
});
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
if (raw.statistics.length === 0) {
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
80
|
+
const result = {};
|
|
81
|
+
for (const entry of raw.statistics) {
|
|
82
|
+
const playerId = entry.player.id;
|
|
83
|
+
const transformed = transformPlayerSeasonStatisticsWithoutTeam(entry);
|
|
84
|
+
if (result[playerId]) {
|
|
85
|
+
result[playerId] = mergePlayerSeasonStatistics(result[playerId], transformed);
|
|
86
|
+
} else {
|
|
87
|
+
result[playerId] = transformed;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
async function getFootballPlayerCareerStatistics(options, config) {
|
|
93
|
+
const finalConfig = config || getConfig();
|
|
94
|
+
const { sportal365Sports } = finalConfig;
|
|
95
|
+
const { playerId, languageCode, next } = options;
|
|
96
|
+
const cacheOptions = next ?? { revalidate: 0 };
|
|
97
|
+
const raw = await footballHttp.get({
|
|
98
|
+
path: `/players/${playerId}/statistics`,
|
|
99
|
+
params: {
|
|
100
|
+
language_code: languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
101
|
+
},
|
|
102
|
+
headers: {
|
|
103
|
+
"Accept-Language": languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
104
|
+
},
|
|
105
|
+
next: cacheOptions,
|
|
106
|
+
config: finalConfig
|
|
107
|
+
});
|
|
108
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`No career statistics found for player ${playerId}. This could be due to: invalid player ID/slug, wrong credentials, or no data available.`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return transformPlayerCareerStatistics(raw);
|
|
114
|
+
}
|
|
115
|
+
async function getFootballPlayerRecentStatistics(options, config) {
|
|
116
|
+
const finalConfig = config || getConfig();
|
|
117
|
+
const { sportal365Sports } = finalConfig;
|
|
118
|
+
const { playerId, matches, tournamentIds, teamId, languageCode, next } = options;
|
|
119
|
+
const cacheOptions = next ?? { revalidate: 0 };
|
|
120
|
+
const params = {
|
|
121
|
+
language_code: languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
122
|
+
};
|
|
123
|
+
if (matches != null) {
|
|
124
|
+
params.matches = String(matches);
|
|
125
|
+
}
|
|
126
|
+
if (tournamentIds?.length) {
|
|
127
|
+
params.tournament_ids = tournamentIds.join(",");
|
|
128
|
+
}
|
|
129
|
+
if (teamId) {
|
|
130
|
+
params.team_id = teamId;
|
|
131
|
+
}
|
|
132
|
+
const raw = await footballHttp.get({
|
|
133
|
+
path: `/v2/statistics/players/${playerId}/recent-statistics`,
|
|
134
|
+
params,
|
|
135
|
+
headers: {
|
|
136
|
+
"Accept-Language": languageCode ?? sportal365Sports?.languageCode ?? "en"
|
|
137
|
+
},
|
|
138
|
+
next: cacheOptions,
|
|
139
|
+
config: finalConfig
|
|
140
|
+
});
|
|
141
|
+
if (!raw.player || !raw.matches) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
`No recent statistics found for player ${playerId}. This could be due to: invalid player ID, wrong credentials, or no data available.`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return transformPlayerRecentStatistics(raw);
|
|
147
|
+
}
|
|
148
|
+
export {
|
|
149
|
+
getFootballPlayerCareerStatistics,
|
|
150
|
+
getFootballPlayerRecentStatistics,
|
|
151
|
+
getFootballPlayerSeasonStatistics,
|
|
152
|
+
getFootballPlayerSeasonStatisticsByPlayerIds
|
|
153
|
+
};
|
|
154
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/lib/api/sportal365-sports/football/statistics/index.ts"],"sourcesContent":["/**\n * Sportal365 Sports API - Football Statistics\n *\n * Fetches player statistics and transforms to canonical FUSports types.\n */\n\nimport type { FUSportsPlayerSeasonStatistics, FUSportsPlayerCareerStatistics, FUSportsPlayerRecentStatistics } from \"../../../../types/canonical\";\nimport { getConfig, type DataLayerConfig } from \"../../../../config\";\nimport { footballHttp } from \"../http\";\nimport type {\n RawPlayerSeasonStatisticsResponse,\n GetFootballPlayerSeasonStatisticsOptions,\n GetFootballPlayerSeasonStatisticsByPlayerIdsOptions,\n} from \"./player-season.types\";\nimport {\n transformPlayerSeasonStatistics,\n transformPlayerSeasonStatisticsWithoutTeam,\n mergePlayerSeasonStatistics,\n} from \"./player-season.transformer\";\nimport type {\n RawPlayerCareerStatisticsResponse,\n GetFootballPlayerCareerStatisticsOptions,\n} from \"./player-career.types\";\nimport { transformPlayerCareerStatistics } from \"./player-career.transformer\";\nimport type {\n RawPlayerRecentStatisticsResponse,\n GetFootballPlayerRecentStatisticsOptions,\n} from \"./player-recent.types\";\nimport { transformPlayerRecentStatistics } from \"./player-recent.transformer\";\n\n// Re-export types for options\nexport type {\n GetFootballPlayerSeasonStatisticsOptions,\n GetFootballPlayerSeasonStatisticsByPlayerIdsOptions,\n} from \"./player-season.types\";\n\nexport type { GetFootballPlayerCareerStatisticsOptions } from \"./player-career.types\";\n\nexport type { GetFootballPlayerRecentStatisticsOptions } from \"./player-recent.types\";\n\n/**\n * Get player season statistics for a team\n *\n * Fetches statistics for all players in a team for the specified season(s).\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 (seasonIds, teamId)\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Map of player ID to canonical FUSportsPlayerSeasonStatistics\n *\n * @example\n * ```typescript\n * const stats = await getFootballPlayerSeasonStatistics({\n * seasonIds: ['8009707'],\n * teamId: '102'\n * });\n * console.log(stats['179118']?.goals); // Player goals\n * ```\n *\n * @example\n * ```typescript\n * // Custom cache duration (5 minutes)\n * const stats = await getFootballPlayerSeasonStatistics({\n * seasonIds: ['8009707'],\n * teamId: '102',\n * next: { revalidate: 300 }\n * });\n * ```\n */\nexport async function getFootballPlayerSeasonStatistics(\n options: GetFootballPlayerSeasonStatisticsOptions,\n config?: DataLayerConfig\n): Promise<Record<string, FUSportsPlayerSeasonStatistics>> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const { seasonIds, teamId, languageCode, next } = options;\n\n // Disable caching to prevent caching of failed/empty responses\n // This ensures we always get fresh data and don't cache API errors\n const cacheOptions = next ?? { revalidate: 0 };\n\n const params = {\n season_ids: seasonIds.join(\",\"),\n team_id: teamId,\n language_code: languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n };\n\n const raw = await footballHttp.get<RawPlayerSeasonStatisticsResponse>({\n path: `/v2/statistics/players/season`,\n params,\n headers: {\n \"Accept-Language\": languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: cacheOptions,\n config: finalConfig,\n });\n\n // Validate response structure\n if (!raw.statistics) {\n console.error(\"[getFootballPlayerSeasonStatistics] Invalid API response - missing statistics array:\", {\n teamId,\n seasonIds,\n response: raw,\n });\n return {};\n }\n\n // Check if statistics array is empty\n if (raw.statistics.length === 0) {\n console.warn(\"[getFootballPlayerSeasonStatistics] API returned empty statistics array:\", {\n teamId,\n seasonIds,\n hint: \"This could be due to: wrong credentials, wrong project header, no data for this team/season, or API issue\",\n });\n\n // Throw an error instead of returning empty object\n // This prevents Next.js from caching the failed response\n throw new Error(\n `No player statistics found for team ${teamId} in seasons ${seasonIds.join(\", \")}. ` +\n `This could be due to: wrong credentials, wrong X-Project header, or no data available for this team/season.`\n );\n }\n\n // Transform to a map of playerId -> statistics\n const result: Record<string, FUSportsPlayerSeasonStatistics> = {};\n\n for (const entry of raw.statistics) {\n const playerId = entry.player.id;\n result[playerId] = transformPlayerSeasonStatistics(entry, teamId);\n }\n\n return result;\n}\n\n/**\n * Get player season statistics by player IDs\n *\n * Fetches statistics for specific players in the specified season(s).\n * Stats are aggregated across all teams the player has played for.\n *\n * @param options - Required parameters (playerIds, seasonIds)\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Map of player ID to canonical FUSportsPlayerSeasonStatistics\n *\n * @example\n * ```typescript\n * const stats = await getFootballPlayerSeasonStatisticsByPlayerIds({\n * playerIds: ['39870'],\n * seasonIds: ['4368438']\n * });\n * console.log(stats['39870']?.goals); // Player goals across all teams\n * ```\n */\nexport async function getFootballPlayerSeasonStatisticsByPlayerIds(\n options: GetFootballPlayerSeasonStatisticsByPlayerIdsOptions,\n config?: DataLayerConfig\n): Promise<Record<string, FUSportsPlayerSeasonStatistics>> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const { playerIds, seasonIds, languageCode, next } = options;\n\n const cacheOptions = next ?? { revalidate: 0 };\n\n const params = {\n player_ids: playerIds.join(\",\"),\n season_ids: seasonIds.join(\",\"),\n language_code: languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n };\n\n const raw = await footballHttp.get<RawPlayerSeasonStatisticsResponse>({\n path: `/v2/statistics/players/season`,\n params,\n headers: {\n \"Accept-Language\": languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: cacheOptions,\n config: finalConfig,\n });\n\n if (!raw.statistics) {\n console.error(\"[getFootballPlayerSeasonStatisticsByPlayerIds] Invalid API response - missing statistics array:\", {\n playerIds,\n seasonIds,\n response: raw,\n });\n return {};\n }\n\n if (raw.statistics.length === 0) {\n return {};\n }\n\n // Transform and merge stats per player (a player may have entries for multiple teams)\n const result: Record<string, FUSportsPlayerSeasonStatistics> = {};\n\n for (const entry of raw.statistics) {\n const playerId = entry.player.id;\n const transformed = transformPlayerSeasonStatisticsWithoutTeam(entry);\n\n if (result[playerId]) {\n result[playerId] = mergePlayerSeasonStatistics(result[playerId], transformed);\n } else {\n result[playerId] = transformed;\n }\n }\n\n return result;\n}\n\n/**\n * Get a player's career statistics across all tournaments and teams\n *\n * Fetches statistics throughout a player's entire career, broken down by\n * tournament season and team.\n *\n * @param options - Required parameters (playerId)\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Player career statistics with per-season-per-team entries\n *\n * @example\n * ```typescript\n * const career = await getFootballPlayerCareerStatistics({\n * playerId: '3400' // or slug: 'cristiano-ronaldo-3400'\n * });\n * console.log(career.playerName); // \"Cristiano Ronaldo\"\n * console.log(career.entries[0].goals); // Goals in first entry\n * ```\n */\nexport async function getFootballPlayerCareerStatistics(\n options: GetFootballPlayerCareerStatisticsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsPlayerCareerStatistics> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const { playerId, languageCode, next } = options;\n\n const cacheOptions = next ?? { revalidate: 0 };\n\n const raw = await footballHttp.get<RawPlayerCareerStatisticsResponse>({\n path: `/players/${playerId}/statistics`,\n params: {\n language_code: languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n headers: {\n \"Accept-Language\": languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: cacheOptions,\n config: finalConfig,\n });\n\n if (!Array.isArray(raw) || raw.length === 0) {\n throw new Error(\n `No career statistics found for player ${playerId}. ` +\n `This could be due to: invalid player ID/slug, wrong credentials, or no data available.`\n );\n }\n\n return transformPlayerCareerStatistics(raw);\n}\n\n/**\n * Get a player's recent statistics from their last N matches\n *\n * Fetches aggregated statistics and match details for a player's most recent matches.\n * Optionally filter by tournament or team.\n *\n * @param options - Required parameters (playerId), optional filters (matches, tournamentIds, teamId)\n * @param config - Optional data layer config (uses singleton if not provided)\n * @returns Player recent statistics with matches and aggregated stats\n *\n * @example\n * ```typescript\n * const recent = await getFootballPlayerRecentStatistics({\n * playerId: '3400',\n * matches: 5\n * });\n * console.log(recent.goals); // Goals in last 5 matches\n * console.log(recent.matches.length); // 5\n * ```\n */\nexport async function getFootballPlayerRecentStatistics(\n options: GetFootballPlayerRecentStatisticsOptions,\n config?: DataLayerConfig\n): Promise<FUSportsPlayerRecentStatistics> {\n const finalConfig = config || getConfig();\n const { sportal365Sports } = finalConfig;\n\n const { playerId, matches, tournamentIds, teamId, languageCode, next } = options;\n\n const cacheOptions = next ?? { revalidate: 0 };\n\n const params: Record<string, string> = {\n language_code: languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n };\n\n if (matches != null) {\n params.matches = String(matches);\n }\n if (tournamentIds?.length) {\n params.tournament_ids = tournamentIds.join(\",\");\n }\n if (teamId) {\n params.team_id = teamId;\n }\n\n const raw = await footballHttp.get<RawPlayerRecentStatisticsResponse>({\n path: `/v2/statistics/players/${playerId}/recent-statistics`,\n params,\n headers: {\n \"Accept-Language\": languageCode ?? sportal365Sports?.languageCode ?? \"en\",\n },\n next: cacheOptions,\n config: finalConfig,\n });\n\n if (!raw.player || !raw.matches) {\n throw new Error(\n `No recent statistics found for player ${playerId}. ` +\n `This could be due to: invalid player ID, wrong credentials, or no data available.`\n );\n }\n\n return transformPlayerRecentStatistics(raw);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function transformCareerEntry(raw) {
|
|
2
|
+
return {
|
|
3
|
+
tournamentSeason: {
|
|
4
|
+
id: String(raw.tournament_season.id),
|
|
5
|
+
name: raw.tournament_season.name,
|
|
6
|
+
uuid: raw.tournament_season.uuid,
|
|
7
|
+
active: raw.tournament_season.active,
|
|
8
|
+
tournament: {
|
|
9
|
+
id: String(raw.tournament_season.tournament.id),
|
|
10
|
+
name: raw.tournament_season.tournament.name,
|
|
11
|
+
uuid: raw.tournament_season.tournament.uuid,
|
|
12
|
+
type: raw.tournament_season.tournament.type,
|
|
13
|
+
region: raw.tournament_season.tournament.region,
|
|
14
|
+
logo: raw.tournament_season.tournament.url_logo,
|
|
15
|
+
country: raw.tournament_season.tournament.country ? {
|
|
16
|
+
id: String(raw.tournament_season.tournament.country.id),
|
|
17
|
+
name: raw.tournament_season.tournament.country.name,
|
|
18
|
+
uuid: raw.tournament_season.tournament.country.uuid
|
|
19
|
+
} : void 0
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
team: {
|
|
23
|
+
id: String(raw.team.id),
|
|
24
|
+
name: raw.team.name,
|
|
25
|
+
uuid: raw.team.uuid,
|
|
26
|
+
threeLetterCode: raw.team.three_letter_code,
|
|
27
|
+
type: raw.team.type,
|
|
28
|
+
logo: raw.team.url_logo
|
|
29
|
+
},
|
|
30
|
+
// Core statistics
|
|
31
|
+
appearances: raw.played,
|
|
32
|
+
started: raw.started,
|
|
33
|
+
substituteIn: raw.substitute_in,
|
|
34
|
+
substituteOut: raw.substitute_out,
|
|
35
|
+
minutes: raw.minutes,
|
|
36
|
+
minutesSubstitute: raw.minutes_substitute,
|
|
37
|
+
// Scoring
|
|
38
|
+
goals: raw.goals,
|
|
39
|
+
goalsSubstitute: raw.goals_substitute,
|
|
40
|
+
penaltyGoals: raw.penalty_goals,
|
|
41
|
+
ownGoals: raw.own_goals,
|
|
42
|
+
assists: raw.assists,
|
|
43
|
+
// Shooting
|
|
44
|
+
shots: raw.shots,
|
|
45
|
+
shotsOnTarget: raw.shots_on_target,
|
|
46
|
+
// Discipline
|
|
47
|
+
yellowCards: raw.yellow_cards,
|
|
48
|
+
redCards: raw.red_cards,
|
|
49
|
+
foulsCommitted: raw.fouls_committed,
|
|
50
|
+
penaltiesCommitted: raw.penalties_committed,
|
|
51
|
+
// Penalties
|
|
52
|
+
penaltiesMissed: raw.penalties_missed,
|
|
53
|
+
penaltiesReceived: raw.penalties_received,
|
|
54
|
+
penaltiesSaved: raw.penalties_saved,
|
|
55
|
+
// Defensive
|
|
56
|
+
cleansheets: raw.cleansheets,
|
|
57
|
+
// Other
|
|
58
|
+
offsides: raw.offsides,
|
|
59
|
+
// Player context
|
|
60
|
+
position: raw.position,
|
|
61
|
+
age: raw.age,
|
|
62
|
+
shirtNumber: raw.shirt_number
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function transformPlayerCareerStatistics(raw) {
|
|
66
|
+
const firstEntry = raw[0];
|
|
67
|
+
return {
|
|
68
|
+
playerId: String(firstEntry.player.id),
|
|
69
|
+
playerName: firstEntry.player.name,
|
|
70
|
+
playerUuid: firstEntry.player.uuid,
|
|
71
|
+
entries: raw.map(transformCareerEntry)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
transformPlayerCareerStatistics
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=player-career.transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-career.transformer.js","sources":["../../../../../src/lib/api/sportal365-sports/football/statistics/player-career.transformer.ts"],"sourcesContent":["/**\n * Player career statistics transformation utilities\n * Transforms raw /players/{id}/statistics responses to canonical FUSports types\n */\n\nimport type {\n FUSportsPlayerCareerStatistics,\n FUSportsPlayerCareerStatisticsEntry,\n} from \"../../../../types/canonical\";\nimport type {\n RawPlayerCareerStatisticsEntry,\n RawPlayerCareerStatisticsResponse,\n} from \"./player-career.types\";\n\n/**\n * Transform a single raw career statistics entry to canonical type\n */\nfunction transformCareerEntry(raw: RawPlayerCareerStatisticsEntry): FUSportsPlayerCareerStatisticsEntry {\n return {\n tournamentSeason: {\n id: String(raw.tournament_season.id),\n name: raw.tournament_season.name,\n uuid: raw.tournament_season.uuid,\n active: raw.tournament_season.active,\n tournament: {\n id: String(raw.tournament_season.tournament.id),\n name: raw.tournament_season.tournament.name,\n uuid: raw.tournament_season.tournament.uuid,\n type: raw.tournament_season.tournament.type,\n region: raw.tournament_season.tournament.region,\n logo: raw.tournament_season.tournament.url_logo,\n country: raw.tournament_season.tournament.country\n ? {\n id: String(raw.tournament_season.tournament.country.id),\n name: raw.tournament_season.tournament.country.name,\n uuid: raw.tournament_season.tournament.country.uuid,\n }\n : undefined,\n },\n },\n team: {\n id: String(raw.team.id),\n name: raw.team.name,\n uuid: raw.team.uuid,\n threeLetterCode: raw.team.three_letter_code,\n type: raw.team.type,\n logo: raw.team.url_logo,\n },\n\n // Core statistics\n appearances: raw.played,\n started: raw.started,\n substituteIn: raw.substitute_in,\n substituteOut: raw.substitute_out,\n minutes: raw.minutes,\n minutesSubstitute: raw.minutes_substitute,\n\n // Scoring\n goals: raw.goals,\n goalsSubstitute: raw.goals_substitute,\n penaltyGoals: raw.penalty_goals,\n ownGoals: raw.own_goals,\n assists: raw.assists,\n\n // Shooting\n shots: raw.shots,\n shotsOnTarget: raw.shots_on_target,\n\n // Discipline\n yellowCards: raw.yellow_cards,\n redCards: raw.red_cards,\n foulsCommitted: raw.fouls_committed,\n penaltiesCommitted: raw.penalties_committed,\n\n // Penalties\n penaltiesMissed: raw.penalties_missed,\n penaltiesReceived: raw.penalties_received,\n penaltiesSaved: raw.penalties_saved,\n\n // Defensive\n cleansheets: raw.cleansheets,\n\n // Other\n offsides: raw.offsides,\n\n // Player context\n position: raw.position,\n age: raw.age,\n shirtNumber: raw.shirt_number,\n };\n}\n\n/**\n * Transform raw player career statistics response to canonical FUSportsPlayerCareerStatistics\n */\nexport function transformPlayerCareerStatistics(\n raw: RawPlayerCareerStatisticsResponse\n): FUSportsPlayerCareerStatistics {\n // Extract player info from the first entry\n const firstEntry = raw[0];\n\n return {\n playerId: String(firstEntry.player.id),\n playerName: firstEntry.player.name,\n playerUuid: firstEntry.player.uuid,\n entries: raw.map(transformCareerEntry),\n };\n}\n"],"names":[],"mappings":"AAiBA,SAAS,qBAAqB,KAA0E;AACpG,SAAO;AAAA,IACH,kBAAkB;AAAA,MACd,IAAI,OAAO,IAAI,kBAAkB,EAAE;AAAA,MACnC,MAAM,IAAI,kBAAkB;AAAA,MAC5B,MAAM,IAAI,kBAAkB;AAAA,MAC5B,QAAQ,IAAI,kBAAkB;AAAA,MAC9B,YAAY;AAAA,QACR,IAAI,OAAO,IAAI,kBAAkB,WAAW,EAAE;AAAA,QAC9C,MAAM,IAAI,kBAAkB,WAAW;AAAA,QACvC,MAAM,IAAI,kBAAkB,WAAW;AAAA,QACvC,MAAM,IAAI,kBAAkB,WAAW;AAAA,QACvC,QAAQ,IAAI,kBAAkB,WAAW;AAAA,QACzC,MAAM,IAAI,kBAAkB,WAAW;AAAA,QACvC,SAAS,IAAI,kBAAkB,WAAW,UACpC;AAAA,UACI,IAAI,OAAO,IAAI,kBAAkB,WAAW,QAAQ,EAAE;AAAA,UACtD,MAAM,IAAI,kBAAkB,WAAW,QAAQ;AAAA,UAC/C,MAAM,IAAI,kBAAkB,WAAW,QAAQ;AAAA,QAAA,IAEnD;AAAA,MAAA;AAAA,IACV;AAAA,IAEJ,MAAM;AAAA,MACF,IAAI,OAAO,IAAI,KAAK,EAAE;AAAA,MACtB,MAAM,IAAI,KAAK;AAAA,MACf,MAAM,IAAI,KAAK;AAAA,MACf,iBAAiB,IAAI,KAAK;AAAA,MAC1B,MAAM,IAAI,KAAK;AAAA,MACf,MAAM,IAAI,KAAK;AAAA,IAAA;AAAA;AAAA,IAInB,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI;AAAA,IACb,cAAc,IAAI;AAAA,IAClB,eAAe,IAAI;AAAA,IACnB,SAAS,IAAI;AAAA,IACb,mBAAmB,IAAI;AAAA;AAAA,IAGvB,OAAO,IAAI;AAAA,IACX,iBAAiB,IAAI;AAAA,IACrB,cAAc,IAAI;AAAA,IAClB,UAAU,IAAI;AAAA,IACd,SAAS,IAAI;AAAA;AAAA,IAGb,OAAO,IAAI;AAAA,IACX,eAAe,IAAI;AAAA;AAAA,IAGnB,aAAa,IAAI;AAAA,IACjB,UAAU,IAAI;AAAA,IACd,gBAAgB,IAAI;AAAA,IACpB,oBAAoB,IAAI;AAAA;AAAA,IAGxB,iBAAiB,IAAI;AAAA,IACrB,mBAAmB,IAAI;AAAA,IACvB,gBAAgB,IAAI;AAAA;AAAA,IAGpB,aAAa,IAAI;AAAA;AAAA,IAGjB,UAAU,IAAI;AAAA;AAAA,IAGd,UAAU,IAAI;AAAA,IACd,KAAK,IAAI;AAAA,IACT,aAAa,IAAI;AAAA,EAAA;AAEzB;AAKO,SAAS,gCACZ,KAC8B;AAE9B,QAAM,aAAa,IAAI,CAAC;AAExB,SAAO;AAAA,IACH,UAAU,OAAO,WAAW,OAAO,EAAE;AAAA,IACrC,YAAY,WAAW,OAAO;AAAA,IAC9B,YAAY,WAAW,OAAO;AAAA,IAC9B,SAAS,IAAI,IAAI,oBAAoB;AAAA,EAAA;AAE7C;"}
|