uefa-api
Version:
Typescript bindings and utils for the UEFA APIs
1 lines • 19.2 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/helpers/matches.ts","../src/utils.ts","../src/helpers/competitions.ts","../src/helpers/livescore.ts","../src/helpers/players.ts","../src/helpers/standings.ts","../src/helpers/teams.ts"],"sourcesContent":["export const apiMatches = 'https://match.uefa.com/v5/matches'\nexport const apiLivescore = 'https://match.uefa.com/v5/livescore'\nexport const apiMatchStats = 'https://matchstats.uefa.com/v1/team-statistics'\nexport const apiCompetitions = 'https://comp.uefa.com/v2/competitions'\nexport const apiTeams = 'https://comp.uefa.com/v2/teams'\nexport const apiPlayers = 'https://comp.uefa.com/v2/players'\nexport const apiStandings = 'https://standings.uefa.com/v1/standings'\n","import type { Lineup, Match, MatchEventDetails, MatchStats } from '../api'\nimport { apiMatchStats, apiMatches } from '../constants'\nimport {\n parseOptionalMixedArray,\n performApiRequest,\n validateLimitOffset\n} from '../utils'\n\nexport enum SortOrder {\n ASCENDING = 'ASC',\n DESCENDING = 'DESC'\n}\n\ninterface FilterCriteria {\n competitionId?: string | number\n groupId?: string | number\n seasonYear?: string | number\n opponentTeamIds?: string | number | (string | number)[]\n order?: SortOrder\n matchId?: string | number | (string | number)[]\n}\n\ntype Parameters = Record<\n keyof Partial<FilterCriteria> | 'limit' | 'offset' | 'order',\n string\n>\n\n/**\n * Get matches based on filter criteria\n * The API response is paginated by a limit and offset, except when filtering by match ids\n *\n * @param filter The criteria to filter matches by (match id, competition id, group id, opponent team ids, season year)\n * @param order Sort order of the matches\n * @param limit Maximum number of matches to return\n * @param offset Number of matches to skip\n * @returns Promise resolving to an array of matches\n */\nexport const getMatches = async (\n filter: FilterCriteria,\n order = SortOrder.ASCENDING,\n limit = 10,\n offset = 0\n): Promise<Match[]> => {\n if (\n !filter ||\n (!filter.competitionId &&\n !filter.groupId &&\n !filter.opponentTeamIds &&\n !filter.matchId &&\n !filter.seasonYear)\n ) {\n throw new Error('At least one filter criteria must be provided')\n }\n\n if (filter.competitionId && !filter.seasonYear) {\n throw new Error(\n 'Season year must be provided when filtering by competition id'\n )\n }\n\n validateLimitOffset(limit, offset)\n\n const parameters = {} as Parameters\n if (filter.competitionId) {\n parameters.competitionId = filter.competitionId.toString()\n }\n if (filter.matchId) {\n parameters.matchId = parseOptionalMixedArray(filter.matchId)\n }\n if (filter.opponentTeamIds) {\n parameters.opponentTeamIds = parseOptionalMixedArray(filter.opponentTeamIds)\n }\n if (filter.groupId) {\n parameters.groupId = filter.groupId.toString()\n }\n if (filter.seasonYear) {\n parameters.seasonYear = filter.seasonYear.toString()\n }\n if (!filter.matchId) {\n parameters.limit = limit.toString()\n parameters.offset = offset.toString()\n }\n parameters.order = order\n\n return performApiRequest<Match[]>(apiMatches, parameters)\n}\n\n/**\n * Get a single match by its id\n *\n * @param matchId The id of the match to retrieve\n * @returns Promise resolving to the match\n * @throws Error if the match is not found\n */\nexport const getMatch = async (matchId: string | number): Promise<Match> => {\n if (!matchId || matchId === '') {\n throw new Error('Match id must be provided')\n }\n const result = await getMatches({ matchId }, SortOrder.ASCENDING, 1, 0)\n if (result.length === 0) {\n throw new Error(`Match with id ${matchId} not found`)\n }\n return result[0]\n}\n\n/**\n * Get match statistics by match id\n *\n * @param matchId The id of the match to retrieve statistics for\n * @returns Promise resolving to the match statistics\n */\nexport const getMatchStats = async (\n matchId: string | number\n): Promise<MatchStats[]> => {\n if (!matchId || matchId === '') {\n throw new Error('Match id must be provided')\n }\n return performApiRequest<MatchStats[]>(`${apiMatchStats}/${matchId}`, {})\n}\n\n/**\n * Get match events by match id\n *\n * @param matchId The id of the match to retrieve events for\n * @param order Sort order of the events\n * @param limit Maximum number of events to return\n * @param offset Number of events to skip\n * @returns Promise resolving to the match events\n */\nexport const getMatchEvents = async (\n matchId: string | number,\n order = SortOrder.ASCENDING,\n limit = 10,\n offset = 0\n): Promise<MatchEventDetails[]> => {\n if (!matchId || matchId === '') {\n throw new Error('Match id must be provided')\n }\n return performApiRequest<MatchEventDetails[]>(\n `${apiMatches}/${matchId}/events`,\n {\n filter: 'LINEUP', // get everything after the lineup\n order,\n limit: limit.toString(),\n offset: offset.toString()\n }\n )\n}\n\n/**\n * Get lineups by match id\n *\n * @param matchId The id of the match to retrieve lineups for\n * @returns Promise resolving to the lineups\n */\nexport const getLineups = async (matchId: string | number): Promise<Lineup> => {\n if (!matchId || matchId === '') {\n throw new Error('Match id must be provided')\n }\n return performApiRequest<Lineup>(`${apiMatches}/${matchId}/lineups`, {})\n}\n","import type { ApiErrorResponse } from './api'\n\nexport const performApiRequest = async <ResultType>(\n apiUrl: string,\n parameters: Record<string, string>\n): Promise<ResultType> => {\n const query = new URLSearchParams(parameters).toString()\n const response = await fetch(`${apiUrl}?${query}`)\n if (!response.ok) {\n throw new Error(`Could not fetch data from API (HTTP ${response.status})`)\n }\n const json = (await response.json()) as ApiErrorResponse\n if (json.error !== undefined) {\n throw new Error(\n `API returned an error: ${json.error.title}, ${json.error.message}`\n )\n }\n return json as ResultType\n}\n\nexport const parseOptionalMixedArray = (\n mixed: string | number | (string | number)[] | undefined\n): string | undefined => {\n if (mixed === undefined) {\n return undefined\n }\n if (Array.isArray(mixed)) {\n return mixed.join(',')\n }\n return mixed.toString()\n}\n\nexport const validateLimitOffset = (limit: number, offset: number): void => {\n if (limit < 1) {\n throw new Error('Limit must be greater than 0')\n }\n\n if (offset < 0) {\n throw new Error('Offset must be greater than or equal to 0')\n }\n}\n","import type { Competition } from '../api'\nimport { apiCompetitions } from '../constants'\nimport { parseOptionalMixedArray, performApiRequest } from '../utils'\n\n/**\n * Returns a list of UEFA competitions, optional matching the provided competition ids\n *\n * @param filterByIds A single competition id, an array of competition ids or undefined to return all competitions\n * @returns A promise that resolves to a list of competitions\n */\nexport const getCompetitions = (\n filterByIds?: number | string | (string | number)[]\n): Promise<Competition[]> => {\n const competitionIds = parseOptionalMixedArray(filterByIds)\n const filter = competitionIds ? { competitionIds } : {}\n return performApiRequest<Competition[]>(apiCompetitions, filter)\n}\n","import type { Livescore } from '../api'\nimport { apiLivescore } from '../constants'\nimport { performApiRequest } from '../utils'\n\n/**\n * Fetches the current livescore from the API.\n * This includes upcoming matches in the near time, live matches and recent matches from the last hours.\n *\n * @returns A promise that resolves with an array of the current livescores.\n */\nexport const getLivescore = (): Promise<Livescore[]> => {\n return performApiRequest<Livescore[]>(apiLivescore, {})\n}\n","import type { Player } from '../api'\nimport { apiPlayers } from '../constants'\nimport {\n parseOptionalMixedArray,\n performApiRequest,\n validateLimitOffset\n} from '../utils'\n\ninterface FilterCriteria {\n competitionId?: string | number\n playerIds?: string | number | (string | number)[]\n seasonYear?: string | number\n}\n\ntype Parameters = Record<\n keyof (Partial<FilterCriteria> & Partial<{ limit: string; offset: string }>),\n string\n>\n\n/**\n * Get player details based on filter criteria\n * The API response is paginated by a limit and offset, except when filtering by player ids\n *\n * @param filter The criteria to filter players by (competition id, player ids, season year)\n * @param limit Maximum number of players to return\n * @param offset Number of players to skip\n * @returns Promise resolving to an array of players\n */\nexport const getPlayers = async (\n filter: FilterCriteria,\n limit = 10,\n offset = 0\n): Promise<Player[]> => {\n if (\n !filter ||\n (!filter.competitionId && !filter.playerIds && !filter.seasonYear)\n ) {\n throw new Error('At least one filter criteria must be provided')\n }\n\n if (filter.competitionId && !filter.seasonYear) {\n throw new Error(\n 'Season year must be provided when filtering by competition id'\n )\n }\n\n validateLimitOffset(limit, offset)\n\n const parameters = {} as Parameters\n if (filter.competitionId) {\n parameters.competitionId = filter.competitionId.toString()\n }\n if (filter.playerIds) {\n parameters.playerIds = parseOptionalMixedArray(filter.playerIds)\n }\n if (filter.seasonYear) {\n parameters.seasonYear = filter.seasonYear.toString()\n }\n if (!filter.playerIds) {\n parameters.limit = limit.toString()\n parameters.offset = offset.toString()\n }\n\n return performApiRequest<Player[]>(apiPlayers, parameters)\n}\n","import type { Standings } from '../api'\nimport { apiStandings } from '../constants'\nimport { parseOptionalMixedArray, performApiRequest } from '../utils'\n\ninterface FilterCriteria {\n competitionId?: string | number\n roundId?: string | number\n groupIds?: string | number | (string | number)[]\n phase?: string\n seasonYear?: string | number\n}\n\ntype Parameters = Record<keyof Partial<FilterCriteria>, string>\n\n/**\n * Get standings based on filter criteria\n *\n * @param filter The criteria to filter standings by (competition id, round id, group ids, phase, season year)\n * @returns Promise resolving to an array of standings\n */\nexport const getStandings = async (\n filter: FilterCriteria\n): Promise<Standings[]> => {\n if (\n !filter ||\n (!filter.competitionId &&\n !filter.roundId &&\n !filter.groupIds &&\n !filter.phase &&\n !filter.seasonYear)\n ) {\n throw new Error('At least one filter criteria must be provided')\n }\n\n if (filter.competitionId && !filter.seasonYear) {\n throw new Error(\n 'Season year must be provided when filtering by competition id'\n )\n }\n\n const parameters = {} as Parameters\n if (filter.competitionId) {\n parameters.competitionId = filter.competitionId.toString()\n }\n if (filter.roundId) {\n parameters.roundId = parseOptionalMixedArray(filter.roundId)\n }\n if (filter.groupIds) {\n parameters.groupIds = parseOptionalMixedArray(filter.groupIds)\n }\n if (filter.phase) {\n parameters.phase = filter.phase.toString()\n }\n if (filter.seasonYear) {\n parameters.seasonYear = filter.seasonYear.toString()\n }\n\n return performApiRequest<Standings[]>(apiStandings, parameters)\n}\n","import type { Team } from '../api'\nimport { apiTeams } from '../constants'\nimport {\n parseOptionalMixedArray,\n performApiRequest,\n validateLimitOffset\n} from '../utils'\n\ninterface FilterCriteria {\n competitionId?: string | number\n roundIds?: string | number | (string | number)[]\n teamIds?: string | number | (string | number)[]\n associationId?: string | number\n seasonYear?: string | number\n}\n\ntype Parameters = Record<\n keyof Partial<FilterCriteria> | 'limit' | 'offset',\n string\n>\n\n/**\n * Get team details based on filter criteria\n * The API response is paginated by a limit and offset, except when filtering by team ids\n *\n * @param filter The criteria to filter teams by (competition id, round ids, team ids, association id, season year)\n * @param limit Maximum number of teams to return\n * @param offset Number of teams to skip\n * @returns Promise resolving to an array of teams\n */\nexport const getTeams = async (\n filter: FilterCriteria,\n limit = 10,\n offset = 0\n): Promise<Team[]> => {\n if (\n !filter ||\n (!filter.competitionId &&\n !filter.roundIds &&\n !filter.teamIds &&\n !filter.associationId &&\n !filter.seasonYear)\n ) {\n throw new Error('At least one filter criteria must be provided')\n }\n\n if (filter.competitionId && !filter.seasonYear) {\n throw new Error(\n 'Season year must be provided when filtering by competition id'\n )\n }\n\n validateLimitOffset(limit, offset)\n\n const parameters = {} as Parameters\n if (filter.competitionId) {\n parameters.competitionId = filter.competitionId.toString()\n }\n if (filter.roundIds) {\n parameters.roundIds = parseOptionalMixedArray(filter.roundIds)\n }\n if (filter.teamIds) {\n parameters.teamIds = parseOptionalMixedArray(filter.teamIds)\n }\n if (filter.associationId) {\n parameters.associationId = filter.associationId.toString()\n }\n if (filter.seasonYear) {\n parameters.seasonYear = filter.seasonYear.toString()\n }\n if (!filter.teamIds) {\n parameters.limit = limit.toString()\n parameters.offset = offset.toString()\n }\n\n return performApiRequest<Team[]>(apiTeams, parameters)\n}\n\n/**\n * Get team details based on team id\n *\n * @param teamId The id of the team to get details for\n * @returns Promise resolving to a team\n * @throws Error if no team is found for the provided id\n */\nexport const getTeam = async (teamId: number | string): Promise<Team> => {\n if (!teamId) {\n throw new Error('Team id must be provided')\n }\n\n const result = await performApiRequest<Team[]>(apiTeams, {\n teamIds: String(teamId),\n limit: '1',\n offset: '0'\n })\n if (result.length !== 1) {\n throw new Error(`No team found for id ${teamId}`)\n }\n return result[0]\n}\n"],"names":["SortOrder","apiMatches","performApiRequest","apiUrl","parameters","query","URLSearchParams","toString","Promise","resolve","fetch","then","response","ok","Error","status","json","undefined","error","title","message","e","reject","parseOptionalMixedArray","mixed","Array","isArray","join","validateLimitOffset","limit","offset","getMatches","filter","order","ASCENDING","competitionId","groupId","opponentTeamIds","matchId","seasonYear","filterByIds","competitionIds","result","length","apiMatchStats","playerIds","roundId","groupIds","phase","roundIds","teamIds","associationId"],"mappings":"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"}