MCPcopy
hub / github.com/holaboss-ai/holaOS / buildAppSdkClient

Function buildAppSdkClient

apps/desktop/electron/appSdkClient.ts:17–97  ·  view source on GitHub ↗
(options: {
  baseURL: string;
  getCookie: () => string;
  onUnauthorized?: () => void;
})

Source from the content-addressed store, hash-verified

15 * before the user signs in. The server decides whether auth is required.
16 */
17export function buildAppSdkClient(options: {
18 baseURL: string;
19 getCookie: () => string;
20 onUnauthorized?: () => void;
21}) {
22 const base = createAppClient({
23 baseURL: options.baseURL,
24 headers: undefined,
25 });
26
27 return async <TData, TError = unknown, TVariables = unknown>(
28 config: RequestConfig<TVariables>
29 ): Promise<ResponseConfig<TData>> => {
30 const headers = new Headers();
31 headers.set("Accept", "application/json");
32 // Do NOT set credentials: "include" — we carry the cookie explicitly and
33 // `credentials: include` would trigger Electron's fetch CORS preflight.
34 const cookie = options.getCookie();
35 if (cookie) {
36 headers.set("Cookie", cookie);
37 }
38 for (const [key, value] of new Headers(
39 (config.headers as HeadersInit | undefined) ?? undefined
40 ).entries()) {
41 headers.set(key, value);
42 }
43
44 try {
45 return await base<TData, TError, TVariables>({
46 ...config,
47 headers,
48 });
49 } catch (error) {
50 const status =
51 error && typeof error === "object" && "status" in error
52 ? (error as { status?: number }).status
53 : undefined;
54 if (status === 401 || status === 403) {
55 options.onUnauthorized?.();
56 // Re-throw with a diagnostic message so the caller can tell whether
57 // the request was even carrying a cookie. This is the single biggest
58 // source of "why am I 401" confusion on the desktop BFF path.
59 const hadCookie = cookie.length > 0;
60 const diagnostic = hadCookie
61 ? `sent Cookie header (${cookie.length} bytes) but server rejected it`
62 : "no Cookie header — Better-Auth session missing or expired. Sign in to desktop first.";
63 // The SDK base client attaches the parsed response body to `.data`
64 // on the error. Surface that so we can see Hono's actual reason.
65 let bodyDump = "";
66 const errData = (error as { data?: unknown }).data;
67 if (errData !== undefined) {
68 try {
69 bodyDump = ` body=${JSON.stringify(errData)}`;
70 } catch {
71 bodyDump = ` body=<unserializable>`;
72 }
73 }
74 // Cookie name hint — shows what names are in the cookie header so we

Callers 1

Calls 1

setMethod · 0.80

Tested by

no test coverage detected