import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import superjson from 'superjson';
import { Agent, fetch } from 'undici';
import { getInternalAuthBearerHeaderIfPresent } from '@nangohq/internal-auth';
import { getInternalTlsOptions } from '@nangohq/utils';
import type { AppRouter } from './server.js';
import type { CreateTRPCProxyClient } from '@trpc/client';
import type { RequestInit } from 'undici';
export type ProxyAppRouter = CreateTRPCProxyClient<AppRouter>;
interface RunnerHttpOpts {
headersTimeoutMs: number;
connectTimeoutMs: number;
responseTimeoutMs: number;
}
export type RunnerClientAuth = {
token?: string | null | undefined;
};
const agents = new Map<string, Agent>();
function getAgent(httpOpts: RunnerHttpOpts): Agent {
const key = `${httpOpts.headersTimeoutMs}:${httpOpts.connectTimeoutMs}:${httpOpts.responseTimeoutMs}`;
let agent = agents.get(key);
if (!agent) {
const tls = getInternalTlsOptions();
agent = new Agent({
headersTimeout: httpOpts.headersTimeoutMs,
connectTimeout: httpOpts.connectTimeoutMs,
bodyTimeout: httpOpts.responseTimeoutMs,
...(tls ? { connect: tls } : {})
});
agents.set(key, agent);
}
return agent;
}
export function getRunnerClient(url: string, httpOpts: RunnerHttpOpts, auth?: RunnerClientAuth): ProxyAppRouter {
const dispatcher = getAgent(httpOpts);
return createTRPCProxyClient<AppRouter>({
transformer: superjson,
links: [
httpBatchLink({
url,
headers: getInternalAuthBearerHeaderIfPresent(auth?.token),
fetch(url: string, options?: RequestInit) {
return fetch(url, {
...options,
dispatcher
});
}
})
]
});
}