2026-07-03 00:09:47 -04:00
|
|
|
import type {
|
|
|
|
|
ArticleContent,
|
|
|
|
|
ChampionshipHub,
|
|
|
|
|
LiveStateResponse,
|
|
|
|
|
Meeting,
|
|
|
|
|
NewsItem,
|
|
|
|
|
RaceHub,
|
|
|
|
|
Session,
|
|
|
|
|
Weekend,
|
|
|
|
|
} from './types'
|
2026-05-25 01:10:44 -04:00
|
|
|
|
|
|
|
|
export async function fetchRaceHub(sessionKey: number): Promise<RaceHub> {
|
|
|
|
|
const res = await fetch(`/api/v1/race-hub?session_key=${sessionKey}`)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
2026-05-25 02:31:35 -04:00
|
|
|
|
|
|
|
|
export async function fetchSeasons(): Promise<number[]> {
|
|
|
|
|
const res = await fetch('/api/v1/seasons')
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
const years = await res.json()
|
|
|
|
|
return Array.isArray(years) ? years : []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function fetchLocalMeetings(year: number): Promise<Meeting[]> {
|
|
|
|
|
const res = await fetch(`/api/v1/meetings?year=${year}&source=local`)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
const meetings = await res.json()
|
|
|
|
|
return Array.isArray(meetings) ? meetings : []
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 18:14:55 -04:00
|
|
|
export async function fetchSeasonMeetings(year: number): Promise<Meeting[]> {
|
|
|
|
|
const res = await fetch(`/api/v1/meetings?year=${year}&source=openf1`)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
const meetings = await res.json()
|
|
|
|
|
return Array.isArray(meetings) ? meetings : []
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-21 19:53:42 -07:00
|
|
|
export async function fetchSessions(meetingKey: number, source = 'openf1'): Promise<Session[]> {
|
|
|
|
|
const res = await fetch(`/api/v1/sessions?meeting_key=${meetingKey}&source=${source}`)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
const sessions = await res.json()
|
|
|
|
|
return Array.isArray(sessions) ? sessions : []
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 02:31:35 -04:00
|
|
|
export async function fetchWeekend(meetingKey: number): Promise<Weekend> {
|
|
|
|
|
const res = await fetch(`/api/v1/weekend?meeting_key=${meetingKey}`)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
2026-05-25 02:56:06 -04:00
|
|
|
|
2026-07-03 00:09:47 -04:00
|
|
|
export async function fetchChampionshipHub(year?: number): Promise<ChampionshipHub> {
|
2026-07-03 01:11:31 -04:00
|
|
|
const params = new URLSearchParams({ source: 'auto' })
|
|
|
|
|
if (year) params.set('year', year.toString())
|
|
|
|
|
const url = `/api/v1/championship/hub?${params.toString()}`
|
2026-07-03 00:09:47 -04:00
|
|
|
const res = await fetch(url)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 02:56:06 -04:00
|
|
|
export async function fetchLiveState(): Promise<LiveStateResponse> {
|
|
|
|
|
const res = await fetch('/api/v1/live/state')
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
2026-05-25 13:04:29 -04:00
|
|
|
|
|
|
|
|
export async function fetchNews(limit?: number, source?: string): Promise<NewsItem[]> {
|
|
|
|
|
const params = new URLSearchParams()
|
|
|
|
|
if (limit) params.set('limit', limit.toString())
|
|
|
|
|
if (source) params.set('source', source)
|
2026-05-25 15:16:00 -04:00
|
|
|
|
2026-05-25 13:04:29 -04:00
|
|
|
const query = params.toString()
|
|
|
|
|
const url = query ? `/api/v1/news?${query}` : '/api/v1/news'
|
2026-05-25 15:16:00 -04:00
|
|
|
|
2026-05-25 13:04:29 -04:00
|
|
|
const res = await fetch(url)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
2026-05-25 15:16:00 -04:00
|
|
|
|
|
|
|
|
export async function fetchNewsArticle(articleUrl: string): Promise<ArticleContent> {
|
|
|
|
|
const res = await fetch(`/api/v1/news/article?url=${encodeURIComponent(articleUrl)}`)
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
throw new Error(`API ${res.status}: ${res.statusText}`)
|
|
|
|
|
}
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function markNewsRead(articleUrl: string): Promise<void> {
|
|
|
|
|
await fetch('/api/v1/news/read', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
body: JSON.stringify({ url: articleUrl }),
|
|
|
|
|
})
|
|
|
|
|
}
|