···
1
+
import type { TBAApiOptions, TBAEvent, TBATeam } from "./tba.types";
3
+
export const DEFAULT_TBA_API_URL = "https://www.thebluealliance.com/api/v3";
5
+
export class TBAApi {
6
+
private apiKey: string;
7
+
private baseUrl: string;
8
+
private cache: Map<string, { etag: string; data: unknown }>;
10
+
constructor(options: TBAApiOptions) {
11
+
this.apiKey = options.apiKey;
12
+
this.baseUrl = options.baseUrl || DEFAULT_TBA_API_URL;
13
+
this.cache = new Map();
16
+
private async fetch<T>(path: string): Promise<T> {
17
+
const url = `${this.baseUrl}${path}`;
18
+
const cachedResponse = this.cache.get(url);
20
+
const headers: Record<string, string> = {
21
+
"X-TBA-Auth-Key": this.apiKey,
24
+
if (cachedResponse?.etag) {
25
+
headers["If-None-Match"] = cachedResponse.etag;
28
+
const response = await fetch(url, { headers });
30
+
if (response.status === 304 && cachedResponse) {
31
+
return cachedResponse.data as T;
36
+
`TBA API error: ${response.status} ${response.statusText}`,
40
+
const data = await response.json();
41
+
const etag = response.headers.get("ETag");
44
+
this.cache.set(url, { etag, data });
50
+
async getEvent(eventKey: string): Promise<TBAEvent> {
51
+
return this.fetch(`/event/${eventKey}`);
54
+
async getTeamsAtEvent(eventKey: string): Promise<TBATeam[]> {
55
+
return this.fetch<TBATeam[]>(`/event/${eventKey}/teams`);
58
+
async getTeam(teamKey: string): Promise<TBATeam> {
59
+
return this.fetch<TBATeam>(`/team/${teamKey}`);
62
+
async getTeamEvents(teamKey: string, year: number): Promise<TBAEvent[]> {
63
+
return this.fetch<TBAEvent[]>(`/team/${teamKey}/events/${year}`);