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(); 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 => { 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, }); }, }); };