diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 0c4aa206..5a9888e6 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -7,13 +7,7 @@ const nextConfig = { domains: ["avatars.githubusercontent.com"], }, assetPrefix: process.env.NEXT_PUBLIC_PIXELEYE_HOSTING === "true" && process.env.NODE_ENV === "production" ? "https://app.pixeleye.io" : undefined, - output: process.env.DOCKER_BUILD === "true" ? "standalone" : undefined, - async rewrites() { - return [{ - source: "/api/:path*", - destination: process.env.BACKEND_URL + "/:path*", - }] - } + output: process.env.DOCKER_BUILD === "true" ? "standalone" : undefined }; module.exports = nextConfig; diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 11eca60f..ce698590 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -4,6 +4,7 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import Providers from "./providers"; import { cx } from "class-variance-authority"; +import { env } from "@/env"; const inter = Inter({ subsets: ["latin"] }); @@ -37,7 +38,9 @@ export default function RootLayout({ "dark:selection:bg-teal-950 dark:selection:text-teal-50 selection:bg-teal-600 selection:text-teal-50 h-fit" )} > - {children} + {children} ); diff --git a/apps/web/src/app/providers.tsx b/apps/web/src/app/providers.tsx index c493d854..5a75dd7c 100644 --- a/apps/web/src/app/providers.tsx +++ b/apps/web/src/app/providers.tsx @@ -1,9 +1,10 @@ "use client"; -import React from "react"; +import React, { useEffect } from "react"; import { LazyMotion } from "framer-motion"; import { ThemeProvider } from "next-themes"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { create } from "zustand"; const loadFeatures = () => import("./features.js").then((res) => res.default); @@ -29,9 +30,20 @@ function getQueryClient() { } } -export default function Providers({ children }: { children: React.ReactNode }) { +export const useBackendURL = create<{ + backendURL?: string; + setBackendURL: (url: string) => void; +}>((set) => ({ + setBackendURL: (url: string) => set({ backendURL: url }), +})); + +export default function Providers({ children, backendURL }: { children: React.ReactNode; backendURL: string }) { const queryClient = getQueryClient() + useEffect(() => { + useBackendURL.setState({ backendURL }); + }, [backendURL]); + return ( diff --git a/apps/web/src/env.ts b/apps/web/src/env.ts index e9ecd00d..9ba7cfd8 100644 --- a/apps/web/src/env.ts +++ b/apps/web/src/env.ts @@ -4,15 +4,13 @@ import { z } from "zod"; export const env = createEnv({ server: { GITHUB_APP_NAME: z.string().optional(), - BACKEND_URL: z.string().optional(), + BACKEND_URL: z.string(), + CLIENT_BACKEND_URL: z.string().optional(), }, client: { - NEXT_PUBLIC_BACKEND_URL: z.string().optional(), NEXT_PUBLIC_PIXELEYE_HOSTING: z.string().optional(), }, experimental__runtimeEnv: { - // eslint-disable-next-line turbo/no-undeclared-env-vars - NEXT_PUBLIC_BACKEND_URL: process.env.NEXT_PUBLIC_BACKEND_URL, // eslint-disable-next-line turbo/no-undeclared-env-vars NEXT_PUBLIC_PIXELEYE_HOSTING: process.env.NEXT_PUBLIC_PIXELEYE_HOSTING, }, @@ -23,6 +21,4 @@ export const env = createEnv({ // If we're on the client, we can use the NEXT_PUBLIC_ environment variables // This is a bit of a hack for docker-compose, since we want our server-side code to access our backend via the docker network export const BACKEND_URL = - (typeof window !== "undefined" - ? env.NEXT_PUBLIC_BACKEND_URL - : env.BACKEND_URL) || env.BACKEND_URL; + typeof window !== "undefined" ? undefined : env.BACKEND_URL; diff --git a/apps/web/src/libs/api.ts b/apps/web/src/libs/api.ts index 80e64a57..663eade3 100644 --- a/apps/web/src/libs/api.ts +++ b/apps/web/src/libs/api.ts @@ -1,3 +1,4 @@ +import { useBackendURL } from "@/app/providers"; import { BACKEND_URL } from "@/env"; import { Services } from "@pixeleye/api"; import { getAPI } from "api-typify"; @@ -11,8 +12,9 @@ export interface CustomProps { }; } -export const createAPI = (extraHeaders: Record = {}) => - getAPI(BACKEND_URL!, (url, options) => +export const createAPI = (extraHeaders: Record = {}) => { + const backendURL = useBackendURL.getState().backendURL || BACKEND_URL!; + return getAPI(backendURL, (url, options) => fetch(url, { ...options, headers: { @@ -37,5 +39,6 @@ export const createAPI = (extraHeaders: Record = {}) => return Promise.reject(await res.json().catch(() => res)); }) ); +}; export const API = createAPI(); diff --git a/apps/web/src/libs/useBuildEvents.ts b/apps/web/src/libs/useBuildEvents.ts index f7808630..bb34a07d 100644 --- a/apps/web/src/libs/useBuildEvents.ts +++ b/apps/web/src/libs/useBuildEvents.ts @@ -5,6 +5,7 @@ import { Build } from "@pixeleye/api"; import { QueryClient, useQueryClient } from "@tanstack/react-query"; import { useEffect } from "react"; import { BACKEND_URL, env } from "../env"; +import { useBackendURL } from "@/app/providers"; interface BuildEvent { buildID: string; @@ -71,9 +72,11 @@ function updateBuildStatus( export function useBuildEvents({ buildID }: BuildEvent) { const queryClient = useQueryClient(); + const backendURL = useBackendURL((state) => state.backendURL) || BACKEND_URL!; + useEffect(() => { const eventSource = new EventSource( - `${BACKEND_URL}/v1/builds/${buildID}/events`, + `${backendURL}/v1/builds/${buildID}/events`, { withCredentials: true, } diff --git a/apps/web/src/libs/useProjectEvents.ts b/apps/web/src/libs/useProjectEvents.ts index 1000a170..b7d99125 100644 --- a/apps/web/src/libs/useProjectEvents.ts +++ b/apps/web/src/libs/useProjectEvents.ts @@ -9,6 +9,7 @@ import { } from "@tanstack/react-query"; import { useEffect } from "react"; import { BACKEND_URL, env } from "../env"; +import { useBackendURL } from "@/app/providers"; interface ProjectEvent { projectID: string; @@ -167,9 +168,11 @@ function newBuild( export function useProjectEvents({ projectID }: ProjectEvent) { const queryClient = useQueryClient(); + const backendURL = useBackendURL((state) => state.backendURL) || BACKEND_URL!; + useEffect(() => { const eventSource = new EventSource( - `${BACKEND_URL}/v1/projects/${projectID}/events`, + `${backendURL}/v1/projects/${projectID}/events`, { withCredentials: true, }