http.ts•1.54 kB
import { ErrorType, ProviderError } from './types.js';
import { handle_rate_limit } from './utils.js';
export interface HttpJsonOptions extends RequestInit {
expectedStatuses?: number[];
}
const tryParseJson = (text: string) => {
if (!text) return undefined;
try {
return JSON.parse(text);
} catch {
return undefined;
}
};
export const http_json = async <T = any>(
provider: string,
url: string,
options: HttpJsonOptions = {},
): Promise<T> => {
const res = await fetch(url, options);
const raw = await res.text();
const body = tryParseJson(raw);
const okOrExpected =
res.ok ||
(options.expectedStatuses &&
options.expectedStatuses.includes(res.status));
if (!okOrExpected) {
const message =
(body && (body.message || body.error || body.detail)) ||
raw ||
res.statusText;
switch (res.status) {
case 401:
throw new ProviderError(
ErrorType.API_ERROR,
'Invalid API key',
provider,
);
case 403:
throw new ProviderError(
ErrorType.API_ERROR,
'API key does not have access to this endpoint',
provider,
);
case 429:
handle_rate_limit(provider);
default:
if (res.status >= 500) {
throw new ProviderError(
ErrorType.PROVIDER_ERROR,
`${provider} API internal error`,
provider,
);
}
throw new ProviderError(
ErrorType.API_ERROR,
`Unexpected error: ${message}`,
provider,
);
}
}
// Prefer JSON if parseable, otherwise return as any
return (body as T) ?? (raw as unknown as T);
};