// Build-time configuration for the Galaxy gateway. Both values arrive // through Vite `import.meta.env` and resolve to module-level constants // at the first import. // // `VITE_GATEWAY_BASE_URL` is the base URL of the gateway public REST // surface. An empty value means "same origin": the single-origin // deployment serves the UI, the REST surface (`/api/...`), and the // authenticated Connect-Web edge (`/rpc/...`) behind one host, so the // browser issues same-origin requests and needs no absolute base. A // non-empty value (the Vite dev proxy, `tools/local-ci`, the // integration suite) points REST at that absolute host instead. The // Connect base is derived from this value by `gatewayRpcBaseUrl`, // which appends the `/rpc` routing prefix. // // `VITE_GATEWAY_RESPONSE_PUBLIC_KEY` is the gateway's response-signing // Ed25519 public key, encoded as standard (non-URL-safe) base64 of // the raw 32-byte key. Decoded once on module load and exported as // `Uint8Array`. The value is only consumed by [GalaxyClient] when a // signed unary call is dispatched; the unauthenticated routes do not // need it. An empty or malformed value therefore does not block app // boot — it surfaces only when the lobby route opens its first // authenticated call. const RAW_BASE_URL: string = (import.meta.env.VITE_GATEWAY_BASE_URL as string | undefined) ?? "http://localhost:8080"; const RAW_RESPONSE_PUBLIC_KEY: string = (import.meta.env.VITE_GATEWAY_RESPONSE_PUBLIC_KEY as string | undefined) ?? ""; export const GATEWAY_BASE_URL: string = stripTrailingSlash(RAW_BASE_URL); /** * gatewayRpcBaseUrl is the base URL for the authenticated Connect-Web * surface. The edge Caddy and the Vite dev proxy route the `/rpc` * prefix to the gateway's Connect listener, stripping it before the * request reaches the proto-derived `edge.v1.Gateway` service path. * When `GATEWAY_BASE_URL` is empty the gateway shares the document * origin, so the origin is resolved at call time from `window`. */ export function gatewayRpcBaseUrl(): string { const origin = GATEWAY_BASE_URL || (typeof window !== "undefined" ? window.location.origin : ""); return `${origin}/rpc`; } export const GATEWAY_RESPONSE_PUBLIC_KEY: Uint8Array = decodeBase64( RAW_RESPONSE_PUBLIC_KEY, ); function stripTrailingSlash(url: string): string { return url.endsWith("/") ? url.slice(0, -1) : url; } function decodeBase64(value: string): Uint8Array { if (value.length === 0) { return new Uint8Array(); } const binary = atob(value); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) { bytes[i] = binary.charCodeAt(i); } return bytes; }