All files / react-app/src/features/package/package-activity hook.ts

91.3% Statements 21/23
50% Branches 2/4
100% Functions 7/7
95.23% Lines 20/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47                72x 8x 4x     8x 2x       2x   2x 3x 3x 3x     2x 2x 2x 2x     2x 2x     2x   2x 1x         8x    
import { getAttachmentUrl } from "@/api";
import JSZip from "jszip";
import { saveAs } from "file-saver";
import { opensearch } from "shared-types";
import { useMutation } from "@tanstack/react-query";
 
export type Attachments = NonNullable<opensearch.changelog.Document["attachments"]>;
 
export const useAttachmentService = ({ packageId }: { packageId: string }) => {
  const { mutateAsync, error, isLoading } = useMutation((attachment: Attachments[number]) =>
    getAttachmentUrl(packageId, attachment.bucket, attachment.key, attachment.filename),
  );
 
  const onZip = (attachments: Attachments) => {
    Iif (attachments.length === 0) {
      return;
    }
 
    const zip = new JSZip();
 
    const remoteZips = attachments.map(async (attachment, index) => {
      const url = await mutateAsync(attachment);
      Iif (!url) return;
      const data = await fetch(url).then((res) => res.blob());
 
      // append index for uniqueness (fileone.md -> fileone(1).md)
      const filename = (() => {
        const pieces = attachment.filename.split(".");
        const ext = pieces.pop();
        return `${pieces.join(".")}(${index + 1}).${ext}`;
      })();
 
      zip.file(filename, data);
      return data;
    });
 
    Promise.allSettled(remoteZips)
      .then(async () => {
        const asyncZipContent = await zip.generateAsync({ type: "blob" });
        saveAs(asyncZipContent, `${packageId} - ${new Date().toDateString()}.zip`);
      })
      .catch(console.error);
  };
 
  return { loading: isLoading, error, onUrl: mutateAsync, onZip };
};