From ba0964f77252d0edf483321f2412f114c2c14cec Mon Sep 17 00:00:00 2001 From: bicochan Date: Thu, 1 Oct 2026 13:44:46 +0900 Subject: [PATCH] =?UTF-8?q?[as]=20feat:=20useTus=20>=20handleError=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/as/src/entities/tus/index.ts | 2 +- apps/as/src/entities/tus/lib/utils.ts | 39 +++++++++++++++++-- apps/as/src/shared/lib/use-tus.ts | 15 ++++--- apps/as/src/shared/ui/file-add-button.tsx | 1 - .../hangulgiangi/ui/hangul-giangi-toolbar.tsx | 4 +- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/apps/as/src/entities/tus/index.ts b/apps/as/src/entities/tus/index.ts index 5cf2e3fbf..58687d0ef 100644 --- a/apps/as/src/entities/tus/index.ts +++ b/apps/as/src/entities/tus/index.ts @@ -1 +1 @@ -export { handleTusUpload, type TusUploadOptions } from "./lib/utils"; +export { handleTusUpload, type TusErrorResponse, type TusUploadOptions } from "./lib/utils"; diff --git a/apps/as/src/entities/tus/lib/utils.ts b/apps/as/src/entities/tus/lib/utils.ts index 6bb40bfd7..96fcd5195 100644 --- a/apps/as/src/entities/tus/lib/utils.ts +++ b/apps/as/src/entities/tus/lib/utils.ts @@ -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; 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 }; diff --git a/apps/as/src/shared/lib/use-tus.ts b/apps/as/src/shared/lib/use-tus.ts index 7a48cad6c..da054fd82 100644 --- a/apps/as/src/shared/lib/use-tus.ts +++ b/apps/as/src/shared/lib/use-tus.ts @@ -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); }, }); diff --git a/apps/as/src/shared/ui/file-add-button.tsx b/apps/as/src/shared/ui/file-add-button.tsx index 36c41406e..922e660b8 100644 --- a/apps/as/src/shared/ui/file-add-button.tsx +++ b/apps/as/src/shared/ui/file-add-button.tsx @@ -40,7 +40,6 @@ function FileAddButton({