import type { WikiSummaryResponse } from "./types.js";
export const WIKIPEDIA_API = "https://en.wikipedia.org/w/api.php";
export const WIKIPEDIA_REST_API = "https://en.wikipedia.org/api/rest_v1";
const REQUEST_TIMEOUT_MS = 30000;
export class WikipediaApiError extends Error {
constructor(
message: string,
public statusCode?: number
) {
super(message);
this.name = "WikipediaApiError";
}
}
async function fetchWithTimeout(url: string, timeoutMs: number = REQUEST_TIMEOUT_MS): Promise<Response> {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { signal: controller.signal });
return response;
} catch (error) {
if (error instanceof Error && error.name === "AbortError") {
throw new WikipediaApiError(`Request timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
clearTimeout(timeoutId);
}
}
export async function queryWikipedia<T>(params: Record<string, string>): Promise<T> {
const searchParams = new URLSearchParams({
...params,
format: "json",
});
const response = await fetchWithTimeout(`${WIKIPEDIA_API}?${searchParams}`);
if (!response.ok) {
throw new WikipediaApiError(`Wikipedia API error: ${response.statusText}`, response.status);
}
return response.json() as Promise<T>;
}
export async function fetchSummary(title: string): Promise<WikiSummaryResponse> {
const url = `${WIKIPEDIA_REST_API}/page/summary/${encodeURIComponent(title)}`;
const response = await fetchWithTimeout(url);
if (!response.ok) {
throw new WikipediaApiError(`Article "${title}" not found`, response.status);
}
return response.json() as Promise<WikiSummaryResponse>;
}
export function textResponse(text: string) {
return {
content: [{ type: "text" as const, text }],
};
}
export function jsonResponse(data: unknown) {
return textResponse(JSON.stringify(data, null, 2));
}
export function errorResponse(error: unknown) {
if (error instanceof WikipediaApiError) {
return textResponse(`Error: ${error.message}`);
}
if (error instanceof Error) {
return textResponse(`Error: ${error.message}`);
}
return textResponse("An unknown error occurred");
}