IKHSAN
EN Read in EnglishID

homeio

Publik

Fork dari doctor-io/homeio

Branch
main
Commit terakhir
958d74616 Oktober 2026

useNetworkShares.ts

Buka raw
"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type {
  CreateNetworkShareRequest,
  DiscoverServersResponse,
  DiscoverSharesRequest,
  DiscoverSharesResponse,
  NetworkShareStatus,
} from "@/lib/shared/contracts/files";
import { queryKeys } from "@/lib/shared/query-keys";

type NetworkSharesResponse = {
  data: NetworkShareStatus[];
  meta?: {
    count: number;
  };
};

type NetworkShareResponse = {
  data: NetworkShareStatus;
};

type DiscoverServersApiResponse = {
  data: DiscoverServersResponse;
};

type DiscoverSharesApiResponse = {
  data: DiscoverSharesResponse;
};

function mapError(responseStatus: number, errorBody: { error?: string; code?: string }) {
  return (
    errorBody.error ??
    `Request failed (${responseStatus})${errorBody.code ? ` [${errorBody.code}]` : ""}`
  );
}

async function listShares() {
  const response = await fetch("/api/v1/files/network/shares", {
    cache: "no-store",
  });

  if (!response.ok) {
    const errorBody = (await response.json().catch(() => ({}))) as {
      error?: string;
      code?: string;
    };
    throw new Error(mapError(response.status, errorBody));
  }

  const json = (await response.json()) as NetworkSharesResponse;
  return json.data;
}

async function createShare(payload: CreateNetworkShareRequest) {
  const response = await fetch("/api/v1/files/network/shares", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    const errorBody = (await response.json().catch(() => ({}))) as {
      error?: string;
      code?: string;
    };
    throw new Error(mapError(response.status, errorBody));
  }

  const json = (await response.json()) as NetworkShareResponse;
  return json.data;
}

async function deleteShare(shareId: string) {
  const response = await fetch(`/api/v1/files/network/shares/${encodeURIComponent(shareId)}`, {
    method: "DELETE",
  });

  if (!response.ok) {
    const errorBody = (await response.json().catch(() => ({}))) as {
      error?: string;
      code?: string;
    };
    throw new Error(mapError(response.status, errorBody));
  }

  return true;
}

async function mountShare(shareId: string) {
  const response = await fetch(
    `/api/v1/files/network/shares/${encodeURIComponent(shareId)}/mount`,
    {
      method: "POST",
    },
  );

  if (!response.ok) {
    const errorBody = (await response.json().catch(() => ({}))) as {
      error?: string;
      code?: string;
    };
    throw new Error(mapError(response.status, errorBody));
  }

  const json = (await response.json()) as NetworkShareResponse;
  return json.data;
}

async function unmountShare(shareId: string) {
  const response = await fetch(
    `/api/v1/files/network/shares/${encodeURIComponent(shareId)}/unmount`,
    {
      method: "POST",
    },
  );

  if (!response.ok) {
    const errorBody = (await response.json().catch(() => ({}))) as {
      error?: string;
      code?: string;
    };
    throw new Error(mapError(response.status, errorBody));
  }

  const json = (await response.json()) as NetworkShareResponse;
  return json.data;
}

async function discoverServers() {
  const response = await fetch("/api/v1/files/network/discover/servers", {
    cache: "no-store",
  });

  if (!response.ok) {
    const errorBody = (await response.json().catch(() => ({}))) as {
      error?: string;
      code?: string;
    };
    throw new Error(mapError(response.status, errorBody));
  }

  const json = (await response.json()) as DiscoverServersApiResponse;
  return json.data;
}

async function discoverHostShares(payload: DiscoverSharesRequest) {
  const response = await fetch("/api/v1/files/network/discover/shares", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    const errorBody = (await response.json().catch(() => ({}))) as {
      error?: string;
      code?: string;
    };
    throw new Error(mapError(response.status, errorBody));
  }

  const json = (await response.json()) as DiscoverSharesApiResponse;
  return json.data;
}

function invalidateNetworkQueries(queryClient: ReturnType<typeof useQueryClient>) {
  void queryClient.invalidateQueries({
    queryKey: queryKeys.networkShares,
  });
  void queryClient.invalidateQueries({
    queryKey: queryKeys.filesList("Network"),
  });
}

export function useNetworkShares() {
  return useQuery({
    queryKey: queryKeys.networkShares,
    queryFn: listShares,
    staleTime: 5_000,
  });
}

export function useCreateNetworkShare() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: createShare,
    onSuccess: () => {
      invalidateNetworkQueries(queryClient);
    },
  });
}

export function useRemoveNetworkShare() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: deleteShare,
    onSuccess: () => {
      invalidateNetworkQueries(queryClient);
    },
  });
}

export function useMountNetworkShare() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: mountShare,
    onSuccess: () => {
      invalidateNetworkQueries(queryClient);
    },
  });
}

export function useUnmountNetworkShare() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: unmountShare,
    onSuccess: () => {
      invalidateNetworkQueries(queryClient);
    },
  });
}

export function useDiscoverNetworkServers() {
  return useMutation({
    mutationFn: discoverServers,
  });
}

export function useDiscoverNetworkShares() {
  return useMutation({
    mutationFn: discoverHostShares,
  });
}
byte
5.702
baris
243
Jenis
ts
Commit terakhir
16 Oktober 2026