IKHSAN
ENID Baca dalam Bahasa Indonesia

homeio

Public

Forked from doctor-io/homeio

Branch
main
Latest commit
958d74616 October 2026

useAppCompose.ts

Open raw
import { useQuery } from "@tanstack/react-query";
import { queryKeys } from "@/lib/shared/query-keys";

export type AppComposeData = {
  image?: string;
  ports?: string[];
  environment?: Record<string, string>;
  volumes?: string[];
  networkMode?: string;
  restart?: string;
  privileged?: boolean;
  capAdd?: string[];
  hostname?: string;
  devices?: string[];
  command?: string | string[];
};

export type AppComposeResponse = {
  compose: string;
  primary: AppComposeData;
  primaryServiceName: string;
};

const APP_COMPOSE_REQUEST_TIMEOUT_MS = 10_000;

/**
 * Fetch and parse the docker-compose.yml for an app from its GitHub repository.
 * Used to pre-fill the app settings dialog with default values.
 */
export function useAppCompose(
  appId: string | undefined,
  enabled = true,
  source: "catalog" | "installed" = "catalog",
) {
  return useQuery({
    queryKey: queryKeys.appCompose(appId ?? "", source),
    queryFn: async () => {
      if (!appId) throw new Error("App ID is required");

      const controller = new AbortController();
      const timeout = setTimeout(() => {
        controller.abort();
      }, APP_COMPOSE_REQUEST_TIMEOUT_MS);

      let response: Response;
      try {
        response = await fetch(
          `/api/v1/store/apps/${appId}/compose?source=${encodeURIComponent(source)}`,
          {
            signal: controller.signal,
          },
        );
      } catch (error) {
        if (error instanceof Error && error.name === "AbortError") {
          throw new Error("Failed to fetch compose file (request timeout)");
        }
        throw error;
      } finally {
        clearTimeout(timeout);
      }

      if (!response.ok) {
        const payload = await response.json().catch(() => null) as
          | { error?: string; code?: string }
          | null;
        const message = payload?.error?.trim() || "Failed to fetch compose file";
        const code = payload?.code?.trim();
        throw new Error(code ? `${message} [${code}]` : message);
      }

      const json = await response.json();
      return json.data as AppComposeResponse;
    },
    enabled: enabled && !!appId,
    staleTime: 5 * 60 * 1000, // 5 minutes
  });
}
bytes
2,201
lines
78
Type
ts
Latest commit
16 October 2026