39 lines · 1.5 KB
import { useMutation } from "@tanstack/react-query";
import { useRouter } from "@tanstack/react-router";
import { errorMessage } from "~/lib/error-message";
import { upsellFromResponse } from "~/lib/upsell";

async function postAsset(owner: string, repo: string, releaseId: string, file: File): Promise<void> {
  const response = await fetch(`/${owner}/${repo}/releases/${releaseId}/assets?name=${encodeURIComponent(file.name)}`, {
    method: "POST",
    headers: { "x-gitfor-csrf": "1", "content-type": file.type || "application/octet-stream" },
    body: file,
  });
  if (!response.ok) {
    const text = await response.text();
    let message = text;
    try {
      const payload = JSON.parse(text) as { error?: string };
      upsellFromResponse(response.status, payload);
      message = payload.error ?? text;
    } catch {
      // Plain-text error.
    }
    throw new Error(message || "Upload failed");
  }
}

/** Release assets stream to a raw Worker route (binary body) rather than a server function. */
export function useReleaseAssetUpload(owner: string, repo: string, releaseId: string) {
  const router = useRouter();
  const mutation = useMutation({
    mutationFn: (file: File) => postAsset(owner, repo, releaseId, file),
    onSuccess: () => router.invalidate({ sync: true }),
  });
  return {
    upload: (file: File) => mutation.mutateAsync(file).catch(() => undefined),
    pending: mutation.isPending,
    error: mutation.isError ? errorMessage(mutation.error) : null,
  };
}