61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import { PROVIDER_LABELS } from "./provider-usage.shared.js";
|
|
import type { ProviderUsageSnapshot, UsageProviderId } from "./provider-usage.types.js";
|
|
|
|
export async function fetchJson(
|
|
url: string,
|
|
init: RequestInit,
|
|
timeoutMs: number,
|
|
fetchFn: typeof fetch,
|
|
): Promise<Response> {
|
|
const controller = new AbortController();
|
|
const timer = setTimeout(controller.abort.bind(controller), timeoutMs);
|
|
try {
|
|
return await fetchFn(url, { ...init, signal: controller.signal });
|
|
} finally {
|
|
clearTimeout(timer);
|
|
}
|
|
}
|
|
|
|
export function parseFiniteNumber(value: unknown): number | undefined {
|
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
return value;
|
|
}
|
|
if (typeof value === "string") {
|
|
const parsed = Number.parseFloat(value);
|
|
if (Number.isFinite(parsed)) {
|
|
return parsed;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
type BuildUsageHttpErrorSnapshotOptions = {
|
|
provider: UsageProviderId;
|
|
status: number;
|
|
message?: string;
|
|
tokenExpiredStatuses?: readonly number[];
|
|
};
|
|
|
|
export function buildUsageErrorSnapshot(
|
|
provider: UsageProviderId,
|
|
error: string,
|
|
): ProviderUsageSnapshot {
|
|
return {
|
|
provider,
|
|
displayName: PROVIDER_LABELS[provider],
|
|
windows: [],
|
|
error,
|
|
};
|
|
}
|
|
|
|
export function buildUsageHttpErrorSnapshot(
|
|
options: BuildUsageHttpErrorSnapshotOptions,
|
|
): ProviderUsageSnapshot {
|
|
const tokenExpiredStatuses = options.tokenExpiredStatuses ?? [];
|
|
if (tokenExpiredStatuses.includes(options.status)) {
|
|
return buildUsageErrorSnapshot(options.provider, "Token expired");
|
|
}
|
|
const suffix = options.message?.trim() ? `: ${options.message.trim()}` : "";
|
|
return buildUsageErrorSnapshot(options.provider, `HTTP ${options.status}${suffix}`);
|
|
}
|