export interface ServerCallOptions { endpoint?: string; signal?: AbortSignal; headers?: HeadersInit; csrfToken?: string; } export class WrnServerCallError extends Error { constructor( message: string, readonly code: string, readonly status: number, readonly details?: unknown, ) { super(message); } } function csrfFromCookie(): string | undefined { if (typeof document === "undefined") return undefined; const raw = /(?:^|;\s*)wrn-csrf=([^;]+)/.exec(document.cookie)?.[1]; return raw ? decodeURIComponent(raw) : undefined; } export async function callServerFunction( component: string, functionName: string, args: TInput, options: ServerCallOptions = {}, ): Promise { const csrfToken = options.csrfToken ?? csrfFromCookie(); const response = await fetch(options.endpoint ?? "/__wrnexus/rpc", { method: "POST", credentials: "same-origin", signal: options.signal, headers: { "content-type": "application/json", ...(csrfToken ? { "x-csrf-token": csrfToken } : {}), ...options.headers, }, body: JSON.stringify({ component, function: functionName, args }), }); const payload = (await response.json().catch(() => null)) as any; if (!response.ok || !payload?.ok) throw new WrnServerCallError( payload?.error?.message ?? `Server call failed (${response.status})`, payload?.error?.code ?? "WRN-RPC-FAILED", response.status, payload?.error?.details, ); return payload.value as TOutput; } export function createServerProxy Promise>>( component: string, options: ServerCallOptions = {}, ): T { return new Proxy({} as T, { get: (_target, property) => (...args: unknown[]) => callServerFunction(component, String(property), args, options), }); }