[as] feat: useTus > handleError 수정

This commit is contained in:
2026-10-01 13:44:46 +09:00
parent 7090f02a52
commit ba0964f772
5 changed files with 48 additions and 13 deletions
+1 -1
View File
@@ -1 +1 @@
export { handleTusUpload, type TusUploadOptions } from "./lib/utils";
export { handleTusUpload, type TusErrorResponse, type TusUploadOptions } from "./lib/utils";
+35 -4
View File
@@ -1,15 +1,29 @@
import { Upload } from "tus-js-client";
import { type DetailedError, Upload } from "tus-js-client";
import { ENDPOINT, PROXY_HOST } from "@/shared/config";
import { AUTH_USER_ID, CLAIM_NAME } from "@/shared/config/env";
import { getCookie } from "@/shared/lib";
interface TusFieldError {
message: string;
field: string;
rejectedValue: string;
}
interface TusErrorResponse {
timestamp: number[];
message: string;
status: number;
code: string;
errors: TusFieldError[];
}
interface TusUploadOptions {
metadata?: Record<string, string>;
handleUploadStart?: (upload: Upload) => void;
handleProgress?: (percentage: number) => void;
handleSuccess?: (upload: Upload, atflCd: string, atflId: string) => void;
handleError?: (error: Error) => void;
handleError?: (error: Error, response: TusErrorResponse | null) => void;
}
function handleTusUpload(file: File, options?: TusUploadOptions) {
@@ -32,7 +46,7 @@ function handleTusUpload(file: File, options?: TusUploadOptions) {
metadata,
onError(error) {
console.error("TUS upload failed:", error);
options?.handleError?.(error);
options?.handleError?.(error, parseTusErrorResponse(error));
},
onProgress(bytesUploaded, bytesTotal) {
const percentage = (bytesUploaded / bytesTotal) * 100;
@@ -57,5 +71,22 @@ function handleTusUpload(file: File, options?: TusUploadOptions) {
return upload;
}
function parseTusErrorResponse(error: Error | DetailedError): TusErrorResponse | null {
if (!("originalResponse" in error)) return null;
const body = error.originalResponse?.getBody();
if (!body) return null;
try {
const parsed: unknown = JSON.parse(body);
if (typeof parsed !== "object" || parsed === null) return null;
if (typeof (parsed as TusErrorResponse).message !== "string") return null;
return parsed as TusErrorResponse;
} catch {
return null;
}
}
export { handleTusUpload };
export type { TusUploadOptions };
export type { TusErrorResponse, TusUploadOptions };
+10 -5
View File
@@ -4,7 +4,7 @@ import { useCallback, useState } from "react";
import { type Upload } from "tus-js-client";
import { handleTusUpload } from "@/entities/tus";
import { handleTusUpload, type TusErrorResponse } from "@/entities/tus";
import { useAlertStore } from "./use-alert-store";
@@ -15,7 +15,12 @@ interface UploadFileOptions {
interface UseTusOptions {
onSuccess?: (atflCd: string, atflId: string, file: File, fileKey: string) => void;
onError?: (error: Error, file: File, fileKey: string) => void;
onError?: (
error: Error,
file: File,
fileKey: string,
response: TusErrorResponse | null,
) => void;
accept?: string;
}
@@ -80,10 +85,10 @@ function useTus(options: UseTusOptions = {}): UseTusReturn {
options.onSuccess?.(atflCd, atflId, file, fileKey);
resolve(atflCd);
},
handleError: (error) => {
handleError: (error, response) => {
setIsUploading((prev) => ({ ...prev, [fileKey]: false }));
alert("파일 업로드 중 오류가 발생했습니다.");
options.onError?.(error, file, fileKey);
alert(response?.message ?? "파일 업로드 중 오류가 발생했습니다.");
options.onError?.(error, file, fileKey, response);
reject(error);
},
});
@@ -40,7 +40,6 @@ function FileAddButton({
<Button
type="button"
size="sm"
variant="outline"
disabled={disabled}
className={cn(
"peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2",
@@ -49,7 +49,7 @@ function HangulGiangiToolbar({
/>
<Button
type="button"
color="white"
variant="outline"
size="sm"
disabled={isBusy}
className={cn(
@@ -58,7 +58,7 @@ function HangulGiangiToolbar({
)}
asChild
>
<span>
<span className="text-[#666]">
<FolderOpen className="!size-5" />
열기
</span>