import { Client, ok, simpleFetchHandler } from '@atcute/client';
import type { Nsid } from '@atcute/lexicons/syntax';
import type { OAuthUserAgent } from '@atcute/oauth-browser-client';
const rpcCache = new Map<string, Client>();
export const normalizeServiceUrl = (input: string): string => {
if (input.startsWith('http://') || input.startsWith('https://')) {
return input;
}
return `https://${input}`;
};
export const getRpc = (service: string): Client => {
const normalized = normalizeServiceUrl(service);
const existing = rpcCache.get(normalized);
if (existing) {
return existing;
}
const client = new Client({
handler: simpleFetchHandler({
service: normalized,
}),
});
rpcCache.set(normalized, client);
return client;
};
export const createAuthRpc = (agent: OAuthUserAgent): Client =>
new Client({
handler: agent,
});
const serviceAudience = (service: string): `did:web:${string}` => {
const url = new URL(normalizeServiceUrl(service));
return `did:web:${url.host}`;
};
export const createServiceAuthRpc = async (
agent: OAuthUserAgent,
service: string,
lxm: Nsid,
): Promise<Client> => {
const authRpc = createAuthRpc(agent);
const { token } = await ok(
authRpc.get('com.atproto.server.getServiceAuth', {
params: {
aud: serviceAudience(service),
exp: Math.floor(Date.now() / 1000) + 60,
lxm,
},
}),
);
const serviceUrl = normalizeServiceUrl(service);
return new Client({
handler: async (pathname, init) => {
const headers = new Headers(init.headers);
headers.set('authorization', `Bearer ${token}`);
return fetch(new URL(pathname, serviceUrl), {
...init,
headers,
});
},
});
};