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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 6x 6x 6x 1x 1x 2x 1x 1x 1x 6x 13x 2x 13x 13x 13x 13x 2x 2x 2x 1x 1x 1x 1x 13x 3x 3x 3x 3x 4x 4x 2x 2x 1x 1x 1x 1x 1x 1x 3x 13x | import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { opensearch } from "shared-types";
import { getAttachmentArchive, getAttachmentUrl } from "@/api";
export type Attachments = NonNullable<opensearch.changelog.Document["attachments"]>;
type AttachmentArchiveRequest = {
scope: "all" | "section";
sectionId?: string;
};
const DEFAULT_POLL_AFTER_SECONDS = 3;
const DEFAULT_ATTACHMENT_ERROR_MESSAGE = "This attachment is no longer available.";
const DEFAULT_ARCHIVE_ERROR_MESSAGE = "Unable to prepare the attachment archive";
function sleep(ms: number) {
return new Promise((resolve) => {
window.setTimeout(resolve, ms);
});
}
function getApiErrorMessage(error: unknown, fallback: string) {
if (
typeof error === "object" &&
error &&
"response" in error &&
error.response &&
typeof error.response === "object" &&
"data" in error.response &&
error.response.data &&
typeof error.response.data === "object" &&
"message" in error.response.data &&
typeof error.response.data.message === "string"
) {
return error.response.data.message;
}
Eif (error instanceof Error && error.message) {
return error.message;
}
return fallback;
}
export const useAttachmentService = ({ packageId }: { packageId: string }) => {
const { mutateAsync, error, isLoading } = useMutation((attachment: Attachments[number]) =>
getAttachmentUrl(packageId, attachment.bucket, attachment.key, attachment.filename),
);
const [archiveLoading, setArchiveLoading] = useState(false);
const [archiveErrorMessage, setArchiveErrorMessage] = useState<string | undefined>();
const [attachmentErrorMessage, setAttachmentErrorMessage] = useState<string | undefined>();
const onUrl = async (attachment: Attachments[number]) => {
setAttachmentErrorMessage(undefined);
try {
return await mutateAsync(attachment);
} catch (attachmentError) {
const message = getApiErrorMessage(attachmentError, DEFAULT_ATTACHMENT_ERROR_MESSAGE);
setAttachmentErrorMessage(message);
console.error(attachmentError);
return undefined;
}
};
const onArchive = async ({
scope,
sectionId,
}: AttachmentArchiveRequest): Promise<string | undefined> => {
setArchiveErrorMessage(undefined);
setArchiveLoading(true);
try {
while (true) {
const response = await getAttachmentArchive(packageId, scope, sectionId);
if (response.status === "READY") {
return response.url;
}
if (response.status === "FAILED") {
throw new Error(response.message || DEFAULT_ARCHIVE_ERROR_MESSAGE);
}
await sleep((response.pollAfterSeconds || DEFAULT_POLL_AFTER_SECONDS) * 1000);
}
} catch (archiveError) {
const message = getApiErrorMessage(archiveError, DEFAULT_ARCHIVE_ERROR_MESSAGE);
setArchiveErrorMessage(message);
console.error(archiveError);
return undefined;
} finally {
setArchiveLoading(false);
}
};
return {
attachmentErrorMessage,
archiveErrorMessage,
error,
loading: isLoading || archiveLoading,
onArchive,
onUrl,
};
};
|