import { cacheManager } from '../cache/manager.js';
import type { Event, EventQueryParams, EventsResponse } from './types.js';
const BASE_URL = 'https://api.open511.gov.bc.ca';
const API_TIMEOUT_MS = 10000;
function generateCacheKey(endpoint: string, params: Record<string, any>): string {
const sortedParams = Object.keys(params)
.sort()
.map(k => `${k}=${params[k]}`)
.join('&');
return `${endpoint}:${sortedParams}`;
}
async function fetchWithRetry(
url: string,
maxRetries: number = 3
): Promise<Response> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT_MS);
const response = await fetch(url, {
headers: {
'Accept': 'application/json',
},
signal: controller.signal,
});
clearTimeout(timeoutId);
return response;
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error('Max retries exceeded');
}
async function fetchFromAPI(
endpoint: string,
params: Record<string, any> = {}
): Promise<any> {
const queryParams = new URLSearchParams({
...params,
format: 'json',
});
const url = `${BASE_URL}${endpoint}?${queryParams}`;
try {
const response = await fetchWithRetry(url);
if (!response.ok) {
throw new Error(`API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
if (error instanceof Error) {
console.error('API request failed:', error.message);
throw new Error(`Failed to fetch from DriveBC API: ${error.message}`);
}
throw error;
}
}
export async function getEvents(params: EventQueryParams = {}): Promise<Event[]> {
const cleanParams: Record<string, any> = {};
if (params.status) cleanParams.status = params.status;
if (params.severity) cleanParams.severity = params.severity;
if (params.event_type) cleanParams.event_type = params.event_type;
if (params.road_name) cleanParams.road_name = params.road_name;
if (params.area_id) cleanParams.area_id = params.area_id;
if (params.limit) cleanParams.limit = params.limit;
if (params.offset) cleanParams.offset = params.offset;
const cacheKey = generateCacheKey('/events', cleanParams);
const cached = cacheManager.get<Event[]>(cacheKey);
if (cached) {
console.error('[Cache HIT]', cacheKey);
return cached;
}
console.error('[Cache MISS]', cacheKey);
const response = await fetchFromAPI('/events', cleanParams);
const events = response.events || [];
cacheManager.set(cacheKey, events, 5 * 60 * 1000);
return events;
}