import type { firstPartyContract } from "@automate.ax/api-contract" import { codecEnvelopeSerializer } from "@automate.ax/codec/rpc" import { createORPCClient } from "@orpc/client" import { RPCLink } from "@orpc/client/fetch" import type { ContractRouterClient } from "@orpc/contract" import { joinURL } from "ufo" import { env } from "./env" import { loadSavedTokenSync } from "./session" export const apiClient: ContractRouterClient = createORPCClient( new RPCLink({ customJsonSerializers: [codecEnvelopeSerializer], headers: () => createApiAuthenticationHeaders({ apiKey: env.AUTOMATE_AX_API_KEY, sessionToken: loadSavedTokenSync(), }), url: joinURL(env.APP_ORIGIN, "/api/rpc"), }), ) /** First-party client that always represents the saved user session. */ export const sessionApiClient: ContractRouterClient = createORPCClient( new RPCLink({ customJsonSerializers: [codecEnvelopeSerializer], headers: () => { const token = loadSavedTokenSync() if (!token) throw new Error("The saved CLI session is unavailable.") return { authorization: `Bearer ${token}` } }, url: joinURL(env.APP_ORIGIN, "/api/rpc"), }), ) /** * Selects the explicit organization API key before a saved user session. * * @param options - Available CLI credentials. * @param options.apiKey - Organization API key supplied through the * environment. * @param options.sessionToken - User session read from the saved CLI login. * @throws When neither credential is available. */ export function createApiAuthenticationHeaders(options: { apiKey?: string sessionToken: string | null }) { const { apiKey, sessionToken } = options if (apiKey) return { "x-api-key": apiKey } if (sessionToken) return { authorization: `Bearer ${sessionToken}` } throw new Error("API credentials are unavailable.") }