Files
Fermi/src/utils.ts
2026-01-02 11:32:31 -06:00

112 lines
2.4 KiB
TypeScript

import {instance} from "./index.js";
interface ApiUrls {
api: string;
gateway: string;
cdn: string;
wellknown: string;
}
export async function getApiUrls(
url: string,
instances: instance[],
check = true,
): Promise<ApiUrls | null> {
if (!url.endsWith("/")) {
url += "/";
}
if (check) {
let valid = false;
for (const instance of instances) {
const urlstr = instance.url || instance.urls?.api;
if (!urlstr) {
continue;
}
try {
if (new URL(urlstr).host === new URL(url).host) {
valid = true;
break;
}
} catch (e) {
//console.log(e);
}
}
if (!valid) {
throw new Error("Invalid instance");
}
}
const hostName = new URL(url).hostname;
try {
return await getApiUrlsV2(url);
} catch (e) {
console.warn(
`[WARN] Failed to get V2 API URLs for ${hostName}, trying V1...`,
(e as Error).message,
);
try {
return await getApiUrlsV1(url);
} catch (e) {
console.error(`[ERROR] Failed to get V1 API URLs for ${hostName}:`, (e as Error).message);
throw e;
}
}
}
//region Well-Known V1 Interfaces
interface WellKnownV1 {
api: string;
}
export async function getApiUrlsV1(url: string): Promise<ApiUrls | null> {
const info: WellKnownV1 = await fetch(`${url}.well-known/spacebar`).then((res) => res.json());
const api = info.api;
const apiUrl = new URL(api);
const policies: any = await fetch(
`${api}${apiUrl.pathname.includes("api") ? "" : "api"}/policies/instance/domains`,
).then((res) => res.json());
return {
api: policies.apiEndpoint,
gateway: policies.gateway,
cdn: policies.cdn,
wellknown: url,
};
}
//endregion
//region Well-Known V2 Interfaces
interface WellKnownV2BasicEndpoint {
baseUrl: string;
}
interface WellKnownV2ApiVersions {
default: string;
active: string[];
}
interface WellKnownV2GatewayOptions {
encoding: ("json" | "etf")[];
compression: ("zlib-stream" | "zstd-stream" | null)[];
}
interface WellKnownV2 {
admin?: WellKnownV2BasicEndpoint;
api: WellKnownV2BasicEndpoint & {apiVersions: WellKnownV2ApiVersions};
cdn: WellKnownV2BasicEndpoint;
gateway: WellKnownV2BasicEndpoint & WellKnownV2GatewayOptions;
}
export async function getApiUrlsV2(url: string): Promise<ApiUrls | null> {
const info: WellKnownV2 = await fetch(`${url}.well-known/spacebar/client`).then((res) =>
res.json(),
);
return {
api: info.api.baseUrl + "/api/v" + info.api.apiVersions.default,
gateway: info.gateway.baseUrl,
cdn: info.cdn.baseUrl,
wellknown: url,
};
}
//endregion