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