@universal-uploader/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/const.d.ts +19 -0
  2. package/dist/createUpload-Bv4Z2y9b.js +155 -0
  3. package/dist/createUpload-Bv4Z2y9b.js.map +1 -0
  4. package/dist/createUpload-CePIp5sg.js +123 -0
  5. package/dist/createUpload-CePIp5sg.js.map +1 -0
  6. package/dist/createUpload-DfsX80rY.js +121 -0
  7. package/dist/createUpload-DfsX80rY.js.map +1 -0
  8. package/dist/createUpload-wm9hFbGi.js +153 -0
  9. package/dist/createUpload-wm9hFbGi.js.map +1 -0
  10. package/dist/createUpload.d.ts +10 -0
  11. package/dist/helper.d.ts +74 -0
  12. package/dist/index-BS99wlKk.js +214 -0
  13. package/dist/index-BS99wlKk.js.map +1 -0
  14. package/dist/index-CZdguoWB.js +216 -0
  15. package/dist/index-CZdguoWB.js.map +1 -0
  16. package/dist/index.cjs +954 -0
  17. package/dist/index.cjs.map +1 -0
  18. package/dist/index.d.ts +144 -0
  19. package/dist/index.js +952 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/orchestrator.d.ts +6 -0
  22. package/dist/stream/helper.d.ts +28 -0
  23. package/dist/stream/index.d.ts +7 -0
  24. package/dist/stream/index.js +79 -0
  25. package/dist/stream-chunked/helper.d.ts +9 -0
  26. package/dist/stream-chunked/index.d.ts +5 -0
  27. package/dist/stream.cjs +249 -0
  28. package/dist/stream.cjs.map +1 -0
  29. package/dist/stream.d.ts +10 -0
  30. package/dist/stream.js +247 -0
  31. package/dist/stream.js.map +1 -0
  32. package/dist/types-CLZnJDsz.d.ts +111 -0
  33. package/dist/types.d.ts +127 -0
  34. package/dist/utils-B4LG-_oN.js +12 -0
  35. package/dist/utils-B4LG-_oN.js.map +1 -0
  36. package/dist/utils-MtT6SgZa.js +10 -0
  37. package/dist/utils-MtT6SgZa.js.map +1 -0
  38. package/dist/utils.d.ts +5 -0
  39. package/dist/xhr-chuncked/helper.d.ts +27 -0
  40. package/dist/xhr-chuncked/index.d.ts +7 -0
  41. package/dist/xhr-chuncked/index.js +181 -0
  42. package/dist/xhr.cjs +142 -0
  43. package/dist/xhr.cjs.map +1 -0
  44. package/dist/xhr.d.ts +10 -0
  45. package/dist/xhr.js +140 -0
  46. package/dist/xhr.js.map +1 -0
  47. package/package.json +34 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/utils.ts","../src/const.ts","../src/helper.ts","../src/stream/helper.ts","../src/stream/index.ts","../src/xhr-chuncked/helper.ts","../src/xhr-chuncked/index.ts","../src/stream-chunked/helper.ts","../src/stream-chunked/index.ts","../src/orchestrator.ts","../src/index.ts"],"sourcesContent":["/**\n * Utility function to wait for a specific duration.\n * 지정된 시간만큼 대기하기 위한 유틸리티 함수입니다.\n */\nexport const wait = (ms: number) =>\n new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n","/**\n * Default chunk size (1 MiB) for stream uploads.\n * Used as both API default and fallback for invalid chunk sizes.\n *\n * 스트림 업로드를 위한 기본 청크 크기(1 MiB)입니다.\n * API 기본값 및 유효하지 않은 청크 크기에 대한 폴백으로 사용됩니다.\n */\nexport const DEFAULT_STREAM_CHUNK_SIZE = 1024 * 1024;\n\n/**\n * Header keys used for chunked upload metadata.\n * 청크 업로드 메타데이터에 사용되는 헤더 키입니다.\n */\nexport const CHUNK_HEADER_KEYS = {\n chunkIndex: \"X-Chunk-Index\",\n totalChunks: \"X-Total-Chunks\",\n chunkSize: \"X-Chunk-Size\",\n fileSize: \"X-File-Size\",\n fileName: \"X-File-Name\",\n} as const;\n","import type { StreamUploaderParams } from \"./types\";\nimport { CHUNK_HEADER_KEYS, DEFAULT_STREAM_CHUNK_SIZE } from \"./const\";\n\n/**\n * Metadata for chunked uploads.\n * 청크 단위 업로드를 위한 메타데이터입니다.\n */\nexport interface ChunkUploadSizesMeta {\n /** Safe size of each chunk. / 안전한 각 청크의 크기. */\n safeChunkSize: number;\n /** Total file size. / 전체 파일 크기. */\n totalFileSize: number;\n /** Total number of chunks. / 전체 청크 수. */\n totalChunks: number;\n}\n\n/**\n * Calculates metadata for chunked uploads, such as safe chunk size and total chunks.\n * 안전한 청크 크기 및 전체 청크 수와 같은 청크 업로드용 메타데이터를 계산합니다.\n */\nexport const calculateSizes = ({\n chunkSize,\n fileSize,\n}: {\n chunkSize: number;\n fileSize: number;\n}): ChunkUploadSizesMeta => {\n const safeChunkSize =\n Number.isFinite(chunkSize) && chunkSize > 0\n ? chunkSize\n : DEFAULT_STREAM_CHUNK_SIZE;\n const totalFileSize = fileSize;\n const totalChunks = Math.ceil(totalFileSize / safeChunkSize);\n\n return {\n safeChunkSize,\n totalFileSize,\n totalChunks,\n };\n};\n\n/**\n * Calculates chunk progress state.\n * 청크 진행 상태(isLastChunk, percentage)를 계산합니다.\n */\nexport const calculateChunkProgress = ({\n loaded,\n total,\n}: {\n loaded: number;\n total: number;\n}) => {\n const isLastChunk = total === 0 || loaded >= total;\n const percentage = isLastChunk ? 100 : (loaded / total) * 100;\n\n return { isLastChunk, percentage };\n};\n\n/**\n * Calculates the resume start position from a persisted offset.\n * 저장된 오프셋으로부터 재개 시작 위치를 계산합니다.\n */\nexport const calculateResumePosition = ({\n offset,\n chunkSize,\n}: {\n offset?: number;\n chunkSize: number;\n}) => {\n const startChunkIndex = Math.floor((offset ?? 0) / chunkSize);\n const startOffset = startChunkIndex * chunkSize;\n\n return { startChunkIndex, startOffset };\n};\n\n/**\n * Creates a Uint8Array buffer from a specific slice of the file.\n * 파일의 특정 부분을 잘라 Uint8Array 버퍼를 생성합니다.\n */\nexport const createBuffer = async ({\n file,\n offset,\n chunkSize,\n}: StreamUploaderParams & { offset: number }) => {\n const chunk = file.slice(offset, offset + chunkSize);\n\n const buffer = await chunk.arrayBuffer();\n\n return new Uint8Array(buffer);\n};\n\n/**\n * Returns chunk-related headers merged with custom headers.\n * 청크 관련 헤더와 커스텀 헤더를 병합해 반환합니다.\n */\nexport const getCustomHeaders = ({\n customHeaders,\n chunkIndex,\n totalChunks,\n chunkSize,\n totalFileSize,\n fileName,\n}: {\n customHeaders?: Record<string, string>;\n chunkIndex?: number;\n totalChunks?: number;\n chunkSize?: number;\n totalFileSize?: number;\n fileName: string;\n}) => {\n const headers: Record<string, string> = {\n [CHUNK_HEADER_KEYS.fileName]: encodeURIComponent(fileName),\n ...(customHeaders || {}),\n };\n\n if (chunkIndex !== undefined) {\n headers[CHUNK_HEADER_KEYS.chunkIndex] = String(chunkIndex);\n }\n\n if (totalChunks !== undefined) {\n headers[CHUNK_HEADER_KEYS.totalChunks] = String(totalChunks);\n }\n\n if (chunkSize !== undefined) {\n headers[CHUNK_HEADER_KEYS.chunkSize] = String(chunkSize);\n }\n\n if (totalFileSize !== undefined) {\n headers[CHUNK_HEADER_KEYS.fileSize] = String(totalFileSize);\n }\n\n return headers;\n};\n\n/**\n * Initializes a RequestInit object and AbortController for streaming uploads.\n * 스트리밍 업로드를 위한 RequestInit 객체 및 AbortController를 초기화합니다.\n */\nexport const initializeStream = ({\n body,\n withCredentials,\n customHeaders,\n}: {\n body: ReadableStream;\n withCredentials: boolean;\n customHeaders: Record<string, string>;\n}) => {\n const abortController = new AbortController();\n\n const streamInit: Readonly<RequestInit> = {\n method: \"POST\",\n body,\n duplex: \"half\",\n signal: abortController.signal,\n credentials: withCredentials ? \"include\" : \"same-origin\",\n headers: {\n \"Content-Type\": \"application/octet-stream\",\n ...(customHeaders || {}),\n },\n };\n\n return { abortController, streamInit };\n};\n","import { createBuffer } from \"../helper\";\nimport type { OnProgressParams, StreamUploaderParams } from \"../types\";\n\n/**\n * Checks if the browser supports ReadableStream upload with Fetch.\n * 브라우저가 Fetch를 통한 ReadableStream 업로드를 지원하는지 확인합니다.\n */\nexport const checkSupportsStreamingUpload = (url: string) => {\n try {\n let duplexAccessed = false;\n\n const hasContentType = new Request(url, {\n body: new ReadableStream(),\n method: \"POST\",\n get duplex(): \"half\" {\n duplexAccessed = true;\n return \"half\";\n },\n }).headers.has(\"Content-Type\");\n\n return duplexAccessed && !hasContentType;\n } catch {\n return false;\n }\n};\n\n/**\n * Returns a ReadableStream that yields chunks of the file.\n * 파일의 청크를 순차적으로 내보내는 ReadableStream을 반환합니다.\n */\nexport const getStreamUploader = ({\n file,\n chunkSize,\n}: StreamUploaderParams) => {\n let offset = 0;\n\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n if (offset >= file.size) {\n controller.close();\n return;\n }\n\n const chunkBuffer = await createBuffer({ file, offset, chunkSize });\n controller.enqueue(chunkBuffer);\n offset += chunkSize;\n\n if (offset >= file.size) {\n controller.close();\n }\n },\n });\n};\n\n/**\n * Creates a TransformStream that tracks the progress of the data flowing through it.\n * 데이터 흐름을 추적하여 진행률을 계산하는 TransformStream을 생성합니다.\n */\nexport const createProgressStream = ({\n totalFileSize,\n onProgress,\n}: {\n totalFileSize: number;\n onProgress?: (args: OnProgressParams) => void;\n}) => {\n let bytesRead = 0;\n\n return new TransformStream<Uint8Array, Uint8Array>({\n // Calculate progress by obtaining chunks from the readable stream piped through. No separate data processing is performed.\n // 각 리더블 스트림에 파이프를 걸어 청크를 얻어 진행율을 계산합니다. 별도의 chunk 데이터 가공은 하지 않습니다.\n transform: (chunk, controller) => {\n bytesRead += chunk.byteLength;\n\n onProgress?.({\n loaded: bytesRead,\n percentage: (bytesRead / totalFileSize) * 100,\n total: totalFileSize,\n });\n\n controller.enqueue(chunk);\n },\n });\n};\n\n/**\n * Creates upload request body with optional progress tracking.\n * 진행률 추적 여부에 따라 업로드 요청 바디를 생성합니다.\n */\nexport const createUploadBody = ({\n stream,\n totalFileSize,\n onProgress,\n}: {\n stream: ReadableStream<Uint8Array>;\n totalFileSize: number;\n onProgress?: (args: OnProgressParams) => void;\n}) =>\n onProgress\n ? stream.pipeThrough(\n createProgressStream({\n totalFileSize,\n onProgress,\n }),\n )\n : stream;\n","import {\n UploadResponse,\n OnProgressParams,\n UploadParams,\n UploadParamsInternal,\n UploadResult,\n} from \"../types\";\nimport { DEFAULT_STREAM_CHUNK_SIZE } from \"../const\";\nimport { calculateSizes, getCustomHeaders, initializeStream } from \"../helper\";\nimport { createUploadBody, getStreamUploader } from \"./helper\";\n\n/**\n * Uploads a file using the Fetch streaming request body.\n * Fetch 스트리밍 요청 바디를 사용하여 파일을 업로드합니다.\n */\nconst uploadWithStream = async ({\n url,\n file,\n resume,\n refresh,\n options: {\n chunkSize = DEFAULT_STREAM_CHUNK_SIZE,\n customHeaders = {},\n withCredentials,\n onProgress,\n onComplete,\n onPause,\n onResume,\n },\n}: UploadParamsInternal): Promise<UploadResponse> => {\n const { safeChunkSize } = calculateSizes({\n chunkSize,\n fileSize: file.size,\n });\n\n const stream = getStreamUploader({ file, chunkSize: safeChunkSize });\n\n const body = createUploadBody({\n stream,\n totalFileSize: file.size,\n onProgress,\n });\n\n const { abortController, streamInit } = initializeStream({\n body,\n withCredentials: withCredentials ?? false,\n customHeaders: getCustomHeaders({ customHeaders, fileName: file.name }),\n });\n\n const response = fetch(url, streamInit);\n let isPaused = false;\n\n return {\n result: response\n .then((res) => {\n if (res.ok) {\n // No chunks are transformed for empty files, so emit terminal progress here.\n if (file.size === 0) {\n onProgress?.({ loaded: 0, total: 0, percentage: 100 });\n }\n\n onComplete?.();\n }\n\n const resultSuccess = {\n ok: res.ok,\n total: file.size,\n message: res.ok\n ? undefined\n : `Upload failed with status ${res.status}`,\n status: res.ok ? \"success\" : \"error\",\n } satisfies UploadResult;\n\n return resultSuccess;\n })\n .catch((e) => {\n if (isPaused && e instanceof DOMException && e.name === \"AbortError\") {\n const resultAborted = {\n ok: false,\n total: file.size,\n message: undefined,\n status: \"paused\",\n } satisfies UploadResult;\n\n return resultAborted;\n }\n\n throw e;\n }),\n actions: {\n abort: () => {\n isPaused = false;\n\n abortController.abort(); // Never put an argument when aborting.\n },\n refresh: () => {\n isPaused = false;\n\n abortController.abort(); // Never put an argument when aborting.\n refresh();\n },\n pause: () => {\n // Actually pause means abort the upload because it is not chunked to catch the chunk upload progress.\n // 실제로 일시정지는 청크 업로드 진행률을 캐치하지 않기 떄문에 업로드를 중단하게 되고 재개 시 업로드를 다시 시작합니다.\n isPaused = true;\n\n abortController.abort();\n onPause?.();\n },\n resume: () => {\n if (!isPaused) {\n return;\n }\n\n isPaused = false;\n\n resume();\n onResume?.();\n },\n },\n };\n};\n\nexport default uploadWithStream;\n","import { getCustomHeaders } from \"../helper\";\n\nconst HTTP_STATUS_SUCCESS_MIN = 200;\nconst HTTP_STATUS_SUCCESS_MAX_EXCLUSIVE = 300;\n\n/**\n * Checks if the given HTTP status code indicates success (2xx).\n * 주어진 HTTP 상태 코드가 성공(2xx)을 나타내는지 확인합니다.\n */\nexport const isSuccessfulHttpStatus = (status: number) =>\n status >= HTTP_STATUS_SUCCESS_MIN &&\n status < HTTP_STATUS_SUCCESS_MAX_EXCLUSIVE;\n\n/**\n * Calculates the end byte position for a specific chunk.\n * 특정 청크의 종료 바이트 위치를 계산합니다.\n */\nexport const calculateChunkEnd = ({\n chunkIndex,\n chunkSize,\n totalFileSize,\n}: {\n chunkIndex: number;\n chunkSize: number;\n totalFileSize: number;\n}) => Math.min((chunkIndex + 1) * chunkSize, totalFileSize);\n\n/**\n * Applies chunking-related headers and custom headers to the XMLHttpRequest object.\n * XMLHttpRequest 객체에 청크 관련 헤더 및 커스텀 헤더를 적용합니다.\n */\nexport const applyChunkHeaders = ({\n xhr,\n customHeaders,\n chunkIndex,\n totalChunks,\n safeChunkSize,\n totalFileSize,\n fileName,\n}: {\n xhr: XMLHttpRequest;\n customHeaders?: Record<string, string>;\n chunkIndex?: number;\n totalChunks?: number;\n safeChunkSize?: number;\n totalFileSize?: number;\n fileName: string;\n}) => {\n const headers = getCustomHeaders({\n customHeaders,\n chunkIndex,\n totalChunks,\n chunkSize: safeChunkSize,\n totalFileSize,\n fileName,\n });\n\n Object.entries(headers).forEach(([key, value]) => {\n xhr.setRequestHeader(key, value);\n });\n};\n","import {\n UploadParams,\n UploadParamsInternal,\n UploadResponse,\n UploadResult,\n} from \"../types\";\nimport {\n isSuccessfulHttpStatus,\n calculateChunkEnd,\n applyChunkHeaders,\n} from \"./helper\";\nimport {\n calculateSizes,\n calculateChunkProgress,\n calculateResumePosition,\n} from \"../helper\";\nimport { DEFAULT_STREAM_CHUNK_SIZE } from \"../const\";\n\n/**\n * Handles file upload as a single request without chunking using XMLHttpRequest.\n * XMLHttpRequest를 사용하여 파일을 청크 분할 없이 단일 요청으로 업로드합니다.\n */\nconst uploadWithoutChunking = ({\n url,\n file,\n refresh,\n resume,\n options: {\n customHeaders = {},\n withCredentials,\n onProgress,\n onComplete,\n onPause,\n onResume,\n },\n}: UploadParamsInternal): UploadResponse => {\n const xhr = new XMLHttpRequest();\n let isPaused = false;\n\n const response = new Promise<UploadResult>((resolve, reject) => {\n xhr.open(\"POST\", url);\n\n if (withCredentials) {\n xhr.withCredentials = true;\n }\n\n applyChunkHeaders({\n xhr,\n customHeaders,\n fileName: file.name,\n });\n\n if (onProgress) {\n xhr.upload.onprogress = (e) => {\n const total = e.total || file.size;\n const percentage = total === 0 ? 100 : (e.loaded / total) * 100;\n\n onProgress({\n loaded: e.loaded,\n total,\n percentage,\n });\n };\n }\n\n xhr.onload = () => {\n if (isSuccessfulHttpStatus(xhr.status)) {\n onProgress?.({ loaded: file.size, total: file.size, percentage: 100 });\n onComplete?.();\n\n resolve({\n ok: true,\n total: file.size,\n message: undefined,\n status: \"success\",\n });\n\n return;\n }\n reject(new Error(`Upload failed with status ${xhr.status}`));\n };\n\n xhr.onabort = () => {\n if (isPaused) {\n resolve({\n ok: false,\n total: file.size,\n message: undefined,\n status: \"paused\",\n });\n return;\n }\n\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n xhr.onerror = () =>\n reject(new Error(`Upload failed with status ${xhr.status}`));\n\n xhr.send(file);\n });\n\n return {\n result: response.then((res) => ({\n ok: res.ok,\n total: file.size,\n message: res.message,\n status: res.status,\n })),\n actions: {\n abort: () => {\n isPaused = false;\n\n xhr.abort();\n },\n refresh: () => {\n isPaused = false;\n\n xhr.abort();\n refresh();\n },\n pause: () => {\n // Actually pause means abort the upload because it is not chunked to catch the chunk upload progress.\n // 실제로 일시정지는 청크 업로드 진행률을 캐치하지 않기 떄문에 업로드를 중단하게 되고 재개 시 업로드를 다시 시작합니다.\n isPaused = true;\n xhr.abort();\n onPause?.();\n },\n resume: () => {\n if (!isPaused) {\n return;\n }\n\n isPaused = false;\n\n resume();\n onResume?.();\n },\n },\n };\n};\n\n/**\n * Uploads a file by splitting it into sequential chunks using XMLHttpRequest.\n * XMLHttpRequest를 사용하여 파일을 여러 개의 청크로 나누어 순차적으로 업로드합니다.\n */\nconst uploadWithXhrChuncked = async (\n args: UploadParamsInternal,\n): Promise<UploadResponse> => {\n const { url, file, refresh, options } = args;\n\n const {\n customHeaders = {},\n withCredentials,\n onProgress,\n onComplete,\n onPause,\n onResume,\n chunkSize,\n } = options;\n\n const response: UploadResponse = {\n result: Promise.resolve({\n ok: false,\n total: 0,\n message: undefined,\n status: \"idle\",\n }),\n actions: {\n abort: () => null,\n refresh: () => null,\n pause: () => null,\n resume: () => null,\n },\n };\n\n // If the chunk size is invalid, upload the file as a single request.\n // 청크 크기가 유효하지 않은 경우 단일 요청으로 업로드합니다.\n if (typeof chunkSize === \"number\" && chunkSize <= 0) {\n return uploadWithoutChunking(args);\n }\n\n const { safeChunkSize, totalFileSize, totalChunks } = calculateSizes({\n chunkSize: chunkSize ?? DEFAULT_STREAM_CHUNK_SIZE,\n fileSize: file.size,\n });\n\n // If the file size is 0, upload the file as a single request.\n // 파일 크기가 0인 경우 바로 성공 처리합니다.\n if (totalFileSize === 0) {\n onProgress?.({ loaded: 0, total: 0, percentage: 100 });\n onComplete?.();\n\n response.result = Promise.resolve({\n ok: true,\n total: 0,\n message: undefined,\n status: \"success\",\n });\n\n return response;\n }\n\n let isResuming = false;\n\n const uploadChunkedXhr = async (): Promise<Readonly<UploadResult>> => {\n isResuming = false;\n\n let uploadResult: Readonly<UploadResult> = {\n ok: false,\n total: 0,\n message: undefined,\n status: \"uploading\",\n };\n\n /**\n * Upload the file by chunks starting from the persisted resume position.\n * options.offset is converted to startChunkIndex/startOffset for resume.\n *\n * 저장된 offset을 기준으로 재개 시작 청크/오프셋을 계산해 업로드를 이어갑니다.\n * 청크 인덱스가 totalChunks보다 작을 때까지 반복합니다.\n */\n const { startChunkIndex, startOffset } = calculateResumePosition({\n offset: options.offset,\n chunkSize: safeChunkSize,\n });\n\n let offset = startOffset;\n\n for (\n let chunkIndex = startChunkIndex;\n chunkIndex < totalChunks;\n chunkIndex += 1\n ) {\n if (uploadResult.status === \"paused\") {\n return uploadResult;\n }\n\n const chunkEnd = calculateChunkEnd({\n chunkIndex,\n chunkSize: safeChunkSize,\n totalFileSize,\n });\n\n const uploadPromise = new Promise<Readonly<UploadResult>>(\n (resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n /**\n * Whether the chunk is paused.\n * 청크가 일시정지된 경우 명시적으로 abort 에러를 던지지 않기 위한 플래그 값.\n */\n let isPaused = false;\n\n if (withCredentials) {\n xhr.withCredentials = true;\n }\n\n xhr.open(\"POST\", url);\n\n applyChunkHeaders({\n xhr,\n customHeaders,\n chunkIndex,\n totalChunks,\n safeChunkSize,\n totalFileSize,\n fileName: file.name,\n });\n\n xhr.onload = () => {\n if (isSuccessfulHttpStatus(xhr.status)) {\n const { isLastChunk, percentage } = calculateChunkProgress({\n loaded: chunkEnd,\n total: totalFileSize,\n });\n\n onProgress?.({\n loaded: chunkEnd,\n total: totalFileSize,\n percentage: totalFileSize === 0 ? 100 : percentage,\n });\n\n if (isLastChunk) {\n onComplete?.();\n }\n\n // 성공 이후에 offset 갱신\n offset = chunkEnd;\n options.offset = chunkEnd;\n\n return resolve({\n ok: true,\n total: totalFileSize,\n message: undefined,\n status: isLastChunk ? \"success\" : \"uploading\",\n });\n }\n\n reject(new Error(`Chunk upload failed with status ${xhr.status}`));\n };\n\n xhr.onerror = () =>\n reject(new Error(`Upload failed with status ${xhr.status}`));\n xhr.onabort = () => {\n // If the chunk is paused, do not reject the promise.\n // 청크가 일시정지된 경우 명시적으로 abort 에러를 던지지 않습니다.\n if (isPaused) {\n return;\n }\n\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n\n const chunk = file.slice(offset, chunkEnd);\n xhr.send(chunk);\n\n // 클로저로 밖에서 참조하는 response.actions 객체를 업데이트합니다.\n response.actions.abort = () => xhr.abort();\n response.actions.refresh = () => {\n xhr.abort();\n refresh();\n };\n response.actions.pause = () => {\n isPaused = true;\n\n xhr.abort();\n onPause?.();\n\n resolve({\n ok: false,\n total: totalFileSize,\n message: undefined,\n status: \"paused\",\n });\n };\n response.actions.resume = () => {\n if (uploadResult.status === \"paused\" && !isResuming) {\n isResuming = true;\n\n // Resume the upload based on the options.offset in the closure. No separate resume function is used because it restarts the upload itself.\n // 업로드를 클로저인 options.offset 기준으로 재개합니다. 별도의 resume 함수는 업로드 자체를 재실행하므로 쓰지 않습니다.\n response.result = uploadChunkedXhr();\n onResume?.();\n }\n };\n },\n );\n uploadResult = await uploadPromise;\n }\n return uploadResult;\n };\n\n response.result = uploadChunkedXhr();\n return response;\n};\n\nexport default uploadWithXhrChuncked;\n","import { createBuffer } from \"../helper\";\n\n/**\n * Returns a ReadableStream that yields a single chunk of the file at the given offset.\n * 지정된 오프셋의 파일 청크를 하나만 내보내는 ReadableStream을 반환합니다.\n */\nexport const createChunkedStream = ({\n file,\n offset,\n chunkSize,\n}: {\n file: File;\n offset: number;\n chunkSize: number;\n}) => {\n const chunkedStream = new ReadableStream<Uint8Array>({\n pull: async (controller) => {\n if (offset >= file.size) {\n controller.close();\n return;\n }\n\n const chunkBuffer = await createBuffer({\n file,\n offset,\n chunkSize,\n });\n\n controller.enqueue(chunkBuffer);\n controller.close();\n },\n });\n\n return chunkedStream;\n};\n","import { UploadParams, UploadResponse, UploadResult } from \"../types\";\nimport { DEFAULT_STREAM_CHUNK_SIZE } from \"../const\";\nimport {\n calculateSizes,\n calculateChunkProgress,\n calculateResumePosition,\n getCustomHeaders,\n initializeStream,\n} from \"../helper\";\nimport { calculateChunkEnd } from \"../xhr-chuncked/helper\";\nimport { createChunkedStream } from \"./helper\";\n\nconst uploadWithFetchStreamChunked = async (\n args: UploadParams & { refresh: () => void },\n): Promise<UploadResponse> => {\n const { url, file, refresh, options } = args;\n\n const {\n chunkSize = DEFAULT_STREAM_CHUNK_SIZE,\n customHeaders = {},\n withCredentials,\n onProgress,\n onComplete,\n onPause,\n onResume,\n } = options;\n\n const response: UploadResponse = {\n result: Promise.resolve({\n ok: false,\n total: 0,\n message: undefined,\n status: \"idle\",\n }),\n actions: {\n abort: () => null,\n refresh: () => null,\n pause: () => null,\n resume: () => null,\n },\n };\n\n const { safeChunkSize, totalFileSize, totalChunks } = calculateSizes({\n chunkSize,\n fileSize: file.size,\n });\n\n if (totalFileSize === 0) {\n onProgress?.({ loaded: 0, total: 0, percentage: 100 });\n onComplete?.();\n\n response.result = Promise.resolve({\n ok: true,\n total: 0,\n message: undefined,\n status: \"success\",\n });\n\n return response;\n }\n\n let isResuming = false;\n\n const uploadChunkedStream = async (): Promise<Readonly<UploadResult>> => {\n isResuming = false;\n\n let uploadResult: Readonly<UploadResult> = {\n ok: false,\n total: 0,\n message: undefined,\n status: \"uploading\",\n };\n\n /**\n * Resume from persisted offset by deriving chunk index + stream offset.\n * 저장된 offset으로부터 재개 시작 청크 인덱스와 오프셋을 계산합니다.\n */\n const { startChunkIndex, startOffset } = calculateResumePosition({\n offset: options.offset,\n chunkSize: safeChunkSize,\n });\n\n let offset = startOffset;\n\n for (\n let chunkIndex = startChunkIndex;\n chunkIndex < totalChunks;\n chunkIndex += 1\n ) {\n if (uploadResult.status === \"paused\") {\n return uploadResult;\n }\n\n const end = calculateChunkEnd({\n chunkIndex,\n chunkSize: safeChunkSize,\n totalFileSize,\n });\n\n const chunkedStream = createChunkedStream({\n file,\n offset,\n chunkSize: safeChunkSize,\n });\n\n const { abortController, streamInit } = initializeStream({\n body: chunkedStream,\n withCredentials: withCredentials ?? false,\n customHeaders: getCustomHeaders({\n customHeaders,\n chunkIndex,\n totalChunks,\n chunkSize: safeChunkSize,\n totalFileSize,\n fileName: file.name,\n }),\n });\n\n /**\n * Whether the chunk is paused.\n * 청크가 일시정지된 경우 명시적으로 abort 에러를 던지지 않기 위한 플래그 값.\n */\n let isPaused = false;\n\n response.actions.abort = () => abortController.abort();\n response.actions.refresh = () => {\n abortController.abort();\n refresh();\n };\n response.actions.pause = () => {\n isPaused = true;\n\n abortController.abort();\n onPause?.();\n\n uploadResult = {\n ok: false,\n total: totalFileSize,\n message: undefined,\n status: \"paused\",\n };\n return;\n };\n response.actions.resume = () => {\n if (uploadResult.status === \"paused\" && !isResuming) {\n isResuming = true;\n\n response.result = uploadChunkedStream();\n onResume?.();\n }\n };\n\n try {\n const fetchResponse = await fetch(url, streamInit);\n\n if (!fetchResponse.ok || fetchResponse.status >= 300) {\n throw new Error(\n `Chunk upload failed with status ${fetchResponse.status}`,\n );\n }\n\n const { isLastChunk, percentage } = calculateChunkProgress({\n loaded: end,\n total: totalFileSize,\n });\n\n onProgress?.({\n loaded: end,\n total: totalFileSize,\n percentage,\n });\n\n if (isLastChunk) {\n onComplete?.();\n }\n\n // 성공 이후에 offset 갱신\n offset = end;\n options.offset = end;\n\n uploadResult = {\n ok: true,\n total: totalFileSize,\n message: undefined,\n status: \"success\",\n };\n } catch (e) {\n if (isPaused && e instanceof DOMException && e.name === \"AbortError\") {\n // Do nothing\n } else {\n throw e;\n }\n }\n }\n\n return uploadResult;\n };\n\n response.result = uploadChunkedStream();\n return response;\n};\n\nexport default uploadWithFetchStreamChunked;\n","import uploadWithStream from \"./stream\";\nimport { checkSupportsStreamingUpload } from \"./stream/helper\";\nimport { UploadOptions } from \"./types\";\nimport uploadWithXhrChuncked from \"./xhr-chuncked\";\nimport uploadWithFetchStreamChunked from \"./stream-chunked\";\n\n/**\n * Returns the appropriate uploader function based on the method and URL.\n * 메서드와 URL에 따라 적절한 업로더 함수를 반환합니다.\n */\nexport const getUploader = (url: string, method: UploadOptions[\"method\"]) => {\n const finalMethod =\n method === \"auto\" && checkSupportsStreamingUpload(url) ? \"stream\" : method;\n\n switch (finalMethod) {\n case \"stream\":\n return uploadWithStream;\n case \"stream chunked\":\n return uploadWithFetchStreamChunked;\n case \"xhr chunked\":\n case \"auto\":\n return uploadWithXhrChuncked;\n default:\n throw new Error(`Unsupported upload method: ${method}`);\n }\n};\n","export * from \"./types\";\nimport { UploadParams, UploadResponse, UploadResult } from \"./types\";\nimport { wait } from \"./utils\";\nimport { getUploader } from \"./orchestrator\";\n\n/**\n * Orchestrates file upload by selecting the optimal method and managing retries and errors.\n * 최적의 업로드 방식을 선택하고 재시도 및 에러 처리를 관리하여 파일 업로드를 수행합니다.\n *\n * retryAttempt: current retry depth used for retry delay/backoff handling.\n * isResuming: true when explicitly resuming so offset reset is skipped.\n * initialOptions: initial call snapshot used to make refresh deterministic.\n *\n * retryAttempt: 현재 재시도 단계(지연/백오프 계산용)입니다.\n * isResuming: 명시적 resume 호출 여부(오프셋 초기화 스킵)입니다.\n * initialOptions: refresh를 항상 동일하게 만들기 위한 최초 옵션 스냅샷입니다.\n */\nconst upload = async (\n { url, file, options: { method = \"auto\", ...options } }: UploadParams,\n retryAttempt = 0,\n isResuming = false,\n initialOptions?: UploadParams[\"options\"],\n): Promise<UploadResponse> => {\n const latestActionsRef: { current?: UploadResponse[\"actions\"] } = {};\n\n const {\n onAbort,\n onRetry,\n onError,\n retryCount: retryCountArg = 3,\n retryDelay = 1000,\n throwOnError = false,\n } = options;\n\n const retryCount = retryCountArg;\n const optionsSnapshot = initialOptions ?? { ...options, method };\n\n /**\n * Keeps externally exposed actions pointing at the latest upload controls.\n * 외부에 노출된 actions가 항상 최신 업로드 제어 함수를 가리키도록 동기화합니다.\n */\n const syncLatestActions = (uploadResponse: UploadResponse) => {\n if (latestActionsRef.current) {\n Object.assign(latestActionsRef.current, uploadResponse.actions);\n }\n\n return uploadResponse;\n };\n\n /**\n * Re-runs upload with shared snapshot/context and optional action sync.\n * 공통 스냅샷/컨텍스트로 업로드를 재실행하고 필요 시 actions를 동기화합니다.\n */\n const runUpload = ({\n uploadArgs,\n nextRetryAttempt = retryAttempt,\n nextIsResuming = false,\n shouldSyncActions = false,\n }: {\n uploadArgs: UploadParams;\n nextRetryAttempt?: number;\n nextIsResuming?: boolean;\n shouldSyncActions?: boolean;\n }) => {\n const uploadTask = upload(\n uploadArgs,\n nextRetryAttempt,\n nextIsResuming,\n optionsSnapshot,\n );\n\n return shouldSyncActions ? uploadTask.then(syncLatestActions) : uploadTask;\n };\n\n if (retryAttempt === 0 && !isResuming) {\n options.offset = undefined;\n }\n\n /**\n * Determines whether to throw an error based on configuration.\n * 구성 설정에 따라 에러를 throw할지 결정합니다.\n */\n const shouldThrowError = (e: unknown): boolean => {\n if (typeof throwOnError === \"function\") {\n return throwOnError(e);\n }\n\n return Boolean(throwOnError);\n };\n\n /**\n * Handles user-triggered aborts.\n * 사용자에 의해 중단된 경우를 처리합니다.\n */\n const handleAbort = (e: DOMException): UploadResult => {\n onAbort?.(e);\n\n if (shouldThrowError(e)) {\n throw e;\n }\n\n return {\n ok: false,\n total: 0,\n message: \"Aborted by user action\",\n status: \"aborted\",\n };\n };\n\n /**\n * Handles generic errors during upload.\n * 업로드 중 발생하는 일반적인 에러를 처리합니다.\n */\n const handleError = (e: Error): UploadResult => {\n onError?.(e);\n\n if (shouldThrowError(e)) {\n throw e;\n }\n\n return { ok: false, total: 0, message: e.message, status: \"error\" };\n };\n\n /**\n * Restart upload from the initial options snapshot.\n * retries/offset are reset to start from scratch.\n *\n * 초기 옵션 스냅샷으로 업로드를 재시작합니다.\n * retries/offset을 초기화하고 처음부터 시작합니다.\n */\n const refresh = () =>\n runUpload({\n uploadArgs: {\n url,\n file,\n options: {\n ...optionsSnapshot,\n offset: 0,\n },\n },\n nextRetryAttempt: 0,\n nextIsResuming: false,\n shouldSyncActions: true,\n });\n\n /**\n * Resume upload using the current retry context and persisted offset.\n * retryAttempt is kept and offset is not reset.\n *\n * 현재 재시도 컨텍스트와 저장된 offset으로 업로드를 재개합니다.\n * retryAttempt를 유지하고 offset을 초기화하지 않습니다.\n */\n const resume = () =>\n runUpload({\n uploadArgs: {\n url,\n file,\n options: {\n ...optionsSnapshot,\n offset: options.offset,\n },\n },\n nextRetryAttempt: retryAttempt,\n nextIsResuming: true,\n shouldSyncActions: true,\n });\n\n /**\n * Attempts to retry an upload operation.\n * 업로드 작업을 재시도합니다.\n */\n const retryUpload = async (\n uploadArgs: UploadParams,\n ): Promise<UploadResponse> => {\n const nextRetryAttempt = retryAttempt + 1;\n\n const nextRetryDelay =\n typeof retryDelay === \"function\"\n ? retryDelay(nextRetryAttempt)\n : retryDelay;\n\n await wait(nextRetryDelay);\n\n const uploadResponse = await runUpload({\n uploadArgs,\n nextRetryAttempt,\n nextIsResuming: false,\n shouldSyncActions: false,\n });\n\n onRetry?.();\n\n return uploadResponse;\n };\n\n /**\n * Wraps the upload operation with error and retry handling.\n * 에러 처리 및 재시도 로직으로 업로드 작업을 래핑합니다.\n */\n const wrapPromiseErrorHandler = async (\n uploadResponse: UploadResponse,\n ): Promise<UploadResponse> => {\n const { result: originalResult, actions: originalActions } = uploadResponse;\n\n const retriedResult: Promise<UploadResult> = originalResult\n .then((uploadResult) => {\n /**\n * fetch resolves for HTTP 4xx/5xx, so stream mode can return { ok: false, status: 'error' }\n * without rejecting. We rethrow here to route it through retry/onError handling.\n *\n * fetch는 HTTP 4xx/5xx에서도 reject하지 않아 stream 모드가 실패 결과를 resolve로 반환할 수 있습니다.\n * 그래서 여기서 다시 throw해서 retry/onError 흐름으로 태웁니다.\n */\n if (!uploadResult.ok && uploadResult.status === \"error\") {\n throw new Error(uploadResult.message || \"Upload failed\");\n }\n\n return uploadResult;\n })\n .catch(async (e) => {\n if (e instanceof DOMException && e.name === \"AbortError\") {\n return handleAbort(e);\n }\n\n if (retryCount > 0) {\n const { result: retryResult, actions: retryActions } =\n await retryUpload({\n url,\n file,\n options: {\n ...options,\n method,\n offset: options.offset,\n retryCount: retryCount - 1,\n },\n });\n\n Object.assign(originalActions, retryActions);\n return retryResult;\n }\n\n return handleError(e as Error);\n });\n\n return { result: Promise.resolve(retriedResult), actions: originalActions };\n };\n\n try {\n const uploadFile = getUploader(url, method);\n\n const uploadResponse = await uploadFile({\n url,\n file,\n refresh,\n resume,\n options,\n });\n\n latestActionsRef.current = uploadResponse.actions;\n\n const uploadResult = await wrapPromiseErrorHandler(uploadResponse);\n\n return uploadResult;\n } catch (e) {\n const uploadResult: UploadResult =\n e instanceof DOMException && e.name === \"AbortError\"\n ? handleAbort(e)\n : handleError(\n e instanceof Error ? e : new Error(\"Unknown upload error\"),\n );\n\n return {\n result: Promise.resolve(uploadResult),\n actions: {\n abort: () => null,\n refresh,\n pause: () => null,\n resume: () => null,\n },\n };\n }\n};\n\nexport default upload;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { UploadOptions } from "./types";
2
+ /**
3
+ * Returns the appropriate uploader function based on the method and URL.
4
+ * 메서드와 URL에 따라 적절한 업로더 함수를 반환합니다.
5
+ */
6
+ export declare const getUploader: (url: string, method: UploadOptions["method"]) => ({ url, file, resume, refresh, options: { chunkSize, customHeaders, withCredentials, onProgress, onComplete, onPause, onResume, }, }: import("./types").UploadParamsInternal) => Promise<import("./types").UploadResponse>;
@@ -0,0 +1,28 @@
1
+ import type { OnProgressParams, StreamUploaderParams } from "../types";
2
+ /**
3
+ * Checks if the browser supports ReadableStream upload with Fetch.
4
+ * 브라우저가 Fetch를 통한 ReadableStream 업로드를 지원하는지 확인합니다.
5
+ */
6
+ export declare const checkSupportsStreamingUpload: (url: string) => boolean;
7
+ /**
8
+ * Returns a ReadableStream that yields chunks of the file.
9
+ * 파일의 청크를 순차적으로 내보내는 ReadableStream을 반환합니다.
10
+ */
11
+ export declare const getStreamUploader: ({ file, chunkSize, }: StreamUploaderParams) => ReadableStream<Uint8Array<ArrayBufferLike>>;
12
+ /**
13
+ * Creates a TransformStream that tracks the progress of the data flowing through it.
14
+ * 데이터 흐름을 추적하여 진행률을 계산하는 TransformStream을 생성합니다.
15
+ */
16
+ export declare const createProgressStream: ({ totalFileSize, onProgress, }: {
17
+ totalFileSize: number;
18
+ onProgress?: (args: OnProgressParams) => void;
19
+ }) => TransformStream<Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>>;
20
+ /**
21
+ * Creates upload request body with optional progress tracking.
22
+ * 진행률 추적 여부에 따라 업로드 요청 바디를 생성합니다.
23
+ */
24
+ export declare const createUploadBody: ({ stream, totalFileSize, onProgress, }: {
25
+ stream: ReadableStream<Uint8Array>;
26
+ totalFileSize: number;
27
+ onProgress?: (args: OnProgressParams) => void;
28
+ }) => ReadableStream<Uint8Array<ArrayBufferLike>>;
@@ -0,0 +1,7 @@
1
+ import { UploadResponse, UploadParamsInternal } from "../types";
2
+ /**
3
+ * Uploads a file using the Fetch streaming request body.
4
+ * Fetch 스트리밍 요청 바디를 사용하여 파일을 업로드합니다.
5
+ */
6
+ declare const uploadWithStream: ({ url, file, resume, refresh, options: { chunkSize, customHeaders, withCredentials, onProgress, onComplete, onPause, onResume, }, }: UploadParamsInternal) => Promise<UploadResponse>;
7
+ export default uploadWithStream;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Default chunk size (1 MiB) for stream uploads.
3
+ * Used as both API default and fallback for invalid chunk sizes.
4
+ */
5
+ const DEFAULT_STREAM_CHUNK_SIZE = 1024 * 1024;
6
+ const createBuffer = async ({ file, offset, chunkSize, }) => {
7
+ const chunk = file.slice(offset, offset + chunkSize);
8
+ const buffer = await chunk.arrayBuffer();
9
+ return new Uint8Array(buffer);
10
+ };
11
+ const getStreamUploader = ({ file, chunkSize }) => {
12
+ let offset = 0;
13
+ return new ReadableStream({
14
+ async pull(controller) {
15
+ if (offset >= file.size) {
16
+ controller.close();
17
+ return;
18
+ }
19
+ const chunkBuffer = await createBuffer({ file, offset, chunkSize });
20
+ controller.enqueue(chunkBuffer);
21
+ offset += chunkSize;
22
+ if (offset >= file.size) {
23
+ controller.close();
24
+ }
25
+ },
26
+ });
27
+ };
28
+ const createProgressStream = ({ totalFileSize, onProgress, }) => {
29
+ let bytesRead = 0;
30
+ return new TransformStream({
31
+ transform(chunk, controller) {
32
+ bytesRead += chunk.byteLength;
33
+ onProgress({
34
+ loaded: bytesRead,
35
+ percentage: (bytesRead / totalFileSize) * 100,
36
+ total: totalFileSize,
37
+ });
38
+ controller.enqueue(chunk);
39
+ },
40
+ });
41
+ };
42
+ /**
43
+ * Uploads a file using the Fetch streaming request body.
44
+ */
45
+ const uploadWithStream = async ({ url, file, refresh, options: { chunkSize = DEFAULT_STREAM_CHUNK_SIZE, customHeaders = {}, onProgress }, }) => {
46
+ const safeChunkSize = Number.isFinite(chunkSize) && chunkSize > 0 ? chunkSize : DEFAULT_STREAM_CHUNK_SIZE;
47
+ const stream = getStreamUploader({ file, chunkSize: safeChunkSize });
48
+ const body = onProgress
49
+ ? stream.pipeThrough(createProgressStream({ totalFileSize: file.size, onProgress }))
50
+ : stream;
51
+ const abortController = new AbortController();
52
+ const init = {
53
+ method: 'POST',
54
+ body,
55
+ duplex: 'half',
56
+ signal: abortController.signal,
57
+ headers: {
58
+ 'Content-Type': 'application/octet-stream',
59
+ ...(customHeaders || {}),
60
+ },
61
+ };
62
+ const response = fetch(url, init);
63
+ return {
64
+ result: response.then((res) => ({
65
+ ok: res.ok,
66
+ total: file.size,
67
+ message: res.ok ? undefined : `Upload failed with status ${res.status}`,
68
+ status: res.ok ? 'success' : 'error',
69
+ })),
70
+ actions: {
71
+ abort: () => abortController.abort(),
72
+ refresh: () => {
73
+ abortController.abort();
74
+ refresh();
75
+ },
76
+ },
77
+ };
78
+ };
79
+ export default uploadWithStream;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Returns a ReadableStream that yields a single chunk of the file at the given offset.
3
+ * 지정된 오프셋의 파일 청크를 하나만 내보내는 ReadableStream을 반환합니다.
4
+ */
5
+ export declare const createChunkedStream: ({ file, offset, chunkSize, }: {
6
+ file: File;
7
+ offset: number;
8
+ chunkSize: number;
9
+ }) => ReadableStream<Uint8Array<ArrayBufferLike>>;
@@ -0,0 +1,5 @@
1
+ import { UploadParams, UploadResponse } from "../types";
2
+ declare const uploadWithFetchStreamChunked: (args: UploadParams & {
3
+ refresh: () => void;
4
+ }) => Promise<UploadResponse>;
5
+ export default uploadWithFetchStreamChunked;
@@ -0,0 +1,249 @@
1
+ 'use strict';
2
+
3
+ var utils = require('./utils-B4LG-_oN.js');
4
+
5
+ /**
6
+ * Default chunk size (1 MiB) for stream uploads.
7
+ * Used as both API default and fallback for invalid chunk sizes.
8
+ *
9
+ * 스트림 업로드를 위한 기본 청크 크기(1 MiB)입니다.
10
+ * API 기본값 및 유효하지 않은 청크 크기에 대한 폴백으로 사용됩니다.
11
+ */
12
+ const DEFAULT_STREAM_CHUNK_SIZE = 1024 * 1024;
13
+ /**
14
+ * Creates a Uint8Array buffer from a specific slice of the file.
15
+ * 파일의 특정 부분을 잘라 Uint8Array 버퍼를 생성합니다.
16
+ */
17
+ const createBuffer = async ({ file, offset, chunkSize, }) => {
18
+ const chunk = file.slice(offset, offset + chunkSize);
19
+ const buffer = await chunk.arrayBuffer();
20
+ return new Uint8Array(buffer);
21
+ };
22
+ /**
23
+ * Returns a ReadableStream that yields chunks of the file.
24
+ * 파일의 청크를 순차적으로 내보내는 ReadableStream을 반환합니다.
25
+ */
26
+ const getStreamUploader = ({ file, chunkSize }) => {
27
+ let offset = 0;
28
+ return new ReadableStream({
29
+ async pull(controller) {
30
+ if (offset >= file.size) {
31
+ controller.close();
32
+ return;
33
+ }
34
+ const chunkBuffer = await createBuffer({ file, offset, chunkSize });
35
+ controller.enqueue(chunkBuffer);
36
+ offset += chunkSize;
37
+ if (offset >= file.size) {
38
+ controller.close();
39
+ }
40
+ },
41
+ });
42
+ };
43
+ /**
44
+ * Creates a TransformStream that tracks the progress of the data flowing through it.
45
+ * 데이터 흐름을 추적하여 진행률을 계산하는 TransformStream을 생성합니다.
46
+ */
47
+ const createProgressStream = ({ totalFileSize, onProgress, }) => {
48
+ let bytesRead = 0;
49
+ return new TransformStream({
50
+ // Calculate progress by obtaining chunks from the readable stream piped through. No separate data processing is performed.
51
+ // 각 리더블 스트림에 파이프를 걸어 청크를 얻어 진행율을 계산합니다. 별도의 chunk 데이터 가공은 하지 않습니다.
52
+ transform: (chunk, controller) => {
53
+ bytesRead += chunk.byteLength;
54
+ onProgress({
55
+ loaded: bytesRead,
56
+ percentage: (bytesRead / totalFileSize) * 100,
57
+ total: totalFileSize,
58
+ });
59
+ controller.enqueue(chunk);
60
+ },
61
+ // Trigger the final progress event once the transform streaming is complete.
62
+ // 변환 스트리밍이 완료되면 마지막 프로그레스 이벤트를 발생시킵니다.
63
+ flush: () => {
64
+ onProgress({
65
+ loaded: totalFileSize,
66
+ percentage: 100,
67
+ total: totalFileSize,
68
+ });
69
+ },
70
+ });
71
+ };
72
+ /**
73
+ * Uploads a file using the Fetch streaming request body.
74
+ * Fetch 스트리밍 요청 바디를 사용하여 파일을 업로드합니다.
75
+ */
76
+ const uploadWithStream = async ({ url, file, refresh, options: { chunkSize = DEFAULT_STREAM_CHUNK_SIZE, customHeaders = {}, onProgress, }, }) => {
77
+ const safeChunkSize = Number.isFinite(chunkSize) && chunkSize > 0
78
+ ? chunkSize
79
+ : DEFAULT_STREAM_CHUNK_SIZE;
80
+ const stream = getStreamUploader({ file, chunkSize: safeChunkSize });
81
+ const body = onProgress
82
+ ? stream.pipeThrough(createProgressStream({ totalFileSize: file.size, onProgress }))
83
+ : stream;
84
+ const abortController = new AbortController();
85
+ const init = {
86
+ method: "POST",
87
+ body,
88
+ duplex: "half",
89
+ signal: abortController.signal,
90
+ headers: {
91
+ "Content-Type": "application/octet-stream",
92
+ ...(customHeaders || {}),
93
+ },
94
+ };
95
+ const response = fetch(url, init);
96
+ return {
97
+ result: response.then((res) => ({
98
+ ok: res.ok,
99
+ total: file.size,
100
+ message: res.ok ? undefined : `Upload failed with status ${res.status}`,
101
+ status: res.ok ? "success" : "error",
102
+ })),
103
+ actions: {
104
+ abort: () => abortController.abort(), // Never put an argument when aborting.
105
+ refresh: () => {
106
+ abortController.abort(); // Never put an argument when aborting.
107
+ refresh();
108
+ },
109
+ },
110
+ };
111
+ };
112
+
113
+ /**
114
+ * Orchestrates file upload by selecting the optimal method and managing retries and errors.
115
+ * 최적의 업로드 방식을 선택하고 재시도 및 에러 처리를 관리하여 파일 업로드를 수행합니다.
116
+ */
117
+ const upload = async ({ url, file, options: { method = "stream", ...options } }, retryAttempt = 0) => {
118
+ const { onComplete, onProgress, onAbort, onRetry, onError, retryCount: retryCountArg = 3, retryDelay = 1000, throwOnError = false, ...restOptions } = options;
119
+ const retryCount = retryCountArg;
120
+ /**
121
+ * Determines whether to throw an error based on configuration.
122
+ * 구성 설정에 따라 에러를 throw할지 결정합니다.
123
+ */
124
+ const shouldThrowError = (e) => {
125
+ if (typeof throwOnError === "function") {
126
+ return throwOnError(e);
127
+ }
128
+ return Boolean(throwOnError);
129
+ };
130
+ /**
131
+ * Handles user-triggered aborts.
132
+ * 사용자에 의해 중단된 경우를 처리합니다.
133
+ */
134
+ const handleAbort = (e) => {
135
+ onAbort?.(e);
136
+ if (shouldThrowError(e)) {
137
+ throw e;
138
+ }
139
+ return {
140
+ ok: false,
141
+ total: 0,
142
+ message: "Aborted by user action",
143
+ status: "aborted",
144
+ };
145
+ };
146
+ /**
147
+ * Handles generic errors during upload.
148
+ * 업로드 중 발생하는 일반적인 에러를 처리합니다.
149
+ */
150
+ const handleError = (e) => {
151
+ onError?.(e);
152
+ if (shouldThrowError(e)) {
153
+ throw e;
154
+ }
155
+ return { ok: false, total: 0, message: e.message, status: "error" };
156
+ };
157
+ const finalOptions = {
158
+ ...restOptions,
159
+ onProgress: ({ loaded, total, percentage }) => {
160
+ onProgress?.({ loaded, total, percentage });
161
+ if (percentage === 100) {
162
+ onComplete?.();
163
+ }
164
+ },
165
+ };
166
+ const refresh = () => upload({ url, file, options });
167
+ /**
168
+ * Attempts to retry an upload operation.
169
+ * 업로드 작업을 재시도합니다.
170
+ */
171
+ const retryUpload = async (uploadArgs) => {
172
+ const nextRetryAttempt = retryAttempt + 1;
173
+ const nextRetryDelay = typeof retryDelay === "function"
174
+ ? retryDelay(nextRetryAttempt)
175
+ : retryDelay;
176
+ await utils.wait(nextRetryDelay);
177
+ const uploadResponse = await upload(uploadArgs, nextRetryAttempt);
178
+ onRetry?.();
179
+ return uploadResponse;
180
+ };
181
+ /**
182
+ * Wraps the upload operation with error and retry handling.
183
+ * 에러 처리 및 재시도 로직으로 업로드 작업을 래핑합니다.
184
+ */
185
+ const wrapPromiseErrorHandler = async (uploadResponse) => {
186
+ const { result: originalResult, actions: originalActions } = uploadResponse;
187
+ const retriedResult = originalResult
188
+ .then((uploadResult) => {
189
+ /**
190
+ * fetch resolves for HTTP 4xx/5xx, so stream mode can return { ok: false, status: 'error' }
191
+ * without rejecting. We rethrow here to route it through retry/onError handling.
192
+ *
193
+ * fetch는 HTTP 4xx/5xx에서도 reject하지 않아 stream 모드가 실패 결과를 resolve로 반환할 수 있습니다.
194
+ * 그래서 여기서 다시 throw해서 retry/onError 흐름으로 태웁니다.
195
+ */
196
+ if (!uploadResult.ok && uploadResult.status === "error") {
197
+ throw new Error(uploadResult.message || "Upload failed");
198
+ }
199
+ return uploadResult;
200
+ })
201
+ .catch(async (e) => {
202
+ if (e instanceof DOMException && e.name === "AbortError") {
203
+ return handleAbort(e);
204
+ }
205
+ if (retryCount > 0) {
206
+ const { result: retryResult, actions: retryActions } = await retryUpload({
207
+ url,
208
+ file,
209
+ options: {
210
+ ...options,
211
+ method,
212
+ retryCount: retryCount - 1,
213
+ },
214
+ });
215
+ Object.assign(originalActions, retryActions);
216
+ return retryResult;
217
+ }
218
+ return handleError(e);
219
+ });
220
+ return { result: Promise.resolve(retriedResult), actions: originalActions };
221
+ };
222
+ try {
223
+ const uploadResult = await wrapPromiseErrorHandler(await uploadWithStream({
224
+ url,
225
+ file,
226
+ refresh,
227
+ options: finalOptions,
228
+ }));
229
+ return uploadResult;
230
+ }
231
+ catch (e) {
232
+ onError?.(e);
233
+ }
234
+ return {
235
+ result: Promise.resolve({
236
+ ok: false,
237
+ total: 0,
238
+ message: "Unsupported upload method",
239
+ status: "error",
240
+ }),
241
+ actions: {
242
+ abort: () => null,
243
+ refresh,
244
+ },
245
+ };
246
+ };
247
+
248
+ module.exports = upload;
249
+ //# sourceMappingURL=stream.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.cjs","sources":["../src/stream/index.ts","../src/stream.ts"],"sourcesContent":["import { UploadParams, UploadResponse, OnProgressParams } from \"../index\";\n\n/**\n * Parameters for stream uploader configuration.\n * 스트림 업로더 구성을 위한 매개변수입니다.\n */\ninterface StreamUploaderParams {\n /** The file to be uploaded. / 업로드할 파일. */\n file: File;\n /** Chunk size in bytes. / 바이트 단위의 청크 크기. */\n chunkSize: number;\n}\n\n/**\n * Default chunk size (1 MiB) for stream uploads.\n * Used as both API default and fallback for invalid chunk sizes.\n *\n * 스트림 업로드를 위한 기본 청크 크기(1 MiB)입니다.\n * API 기본값 및 유효하지 않은 청크 크기에 대한 폴백으로 사용됩니다.\n */\nconst DEFAULT_STREAM_CHUNK_SIZE = 1024 * 1024;\n\n/**\n * Creates a Uint8Array buffer from a specific slice of the file.\n * 파일의 특정 부분을 잘라 Uint8Array 버퍼를 생성합니다.\n */\nconst createBuffer = async ({\n file,\n offset,\n chunkSize,\n}: StreamUploaderParams & { offset: number }) => {\n const chunk = file.slice(offset, offset + chunkSize);\n\n const buffer = await chunk.arrayBuffer();\n\n return new Uint8Array(buffer);\n};\n\n/**\n * Returns a ReadableStream that yields chunks of the file.\n * 파일의 청크를 순차적으로 내보내는 ReadableStream을 반환합니다.\n */\nconst getStreamUploader = ({ file, chunkSize }: StreamUploaderParams) => {\n let offset = 0;\n\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n if (offset >= file.size) {\n controller.close();\n return;\n }\n\n const chunkBuffer = await createBuffer({ file, offset, chunkSize });\n controller.enqueue(chunkBuffer);\n offset += chunkSize;\n\n if (offset >= file.size) {\n controller.close();\n }\n },\n });\n};\n\n/**\n * Creates a TransformStream that tracks the progress of the data flowing through it.\n * 데이터 흐름을 추적하여 진행률을 계산하는 TransformStream을 생성합니다.\n */\nconst createProgressStream = ({\n totalFileSize,\n onProgress,\n}: {\n totalFileSize: number;\n onProgress: (args: OnProgressParams) => void;\n}) => {\n let bytesRead = 0;\n\n return new TransformStream<Uint8Array, Uint8Array>({\n // Calculate progress by obtaining chunks from the readable stream piped through. No separate data processing is performed.\n // 각 리더블 스트림에 파이프를 걸어 청크를 얻어 진행율을 계산합니다. 별도의 chunk 데이터 가공은 하지 않습니다.\n transform: (chunk, controller) => {\n bytesRead += chunk.byteLength;\n onProgress({\n loaded: bytesRead,\n percentage: (bytesRead / totalFileSize) * 100,\n total: totalFileSize,\n });\n\n controller.enqueue(chunk);\n },\n\n // Trigger the final progress event once the transform streaming is complete.\n // 변환 스트리밍이 완료되면 마지막 프로그레스 이벤트를 발생시킵니다.\n flush: () => {\n onProgress({\n loaded: totalFileSize,\n percentage: 100,\n total: totalFileSize,\n });\n },\n });\n};\n\n/**\n * Uploads a file using the Fetch streaming request body.\n * Fetch 스트리밍 요청 바디를 사용하여 파일을 업로드합니다.\n */\nconst uploadWithStream = async ({\n url,\n file,\n refresh,\n options: {\n chunkSize = DEFAULT_STREAM_CHUNK_SIZE,\n customHeaders = {},\n onProgress,\n },\n}: UploadParams & { refresh: () => void }): Promise<UploadResponse> => {\n const safeChunkSize =\n Number.isFinite(chunkSize) && chunkSize > 0\n ? chunkSize\n : DEFAULT_STREAM_CHUNK_SIZE;\n\n const stream = getStreamUploader({ file, chunkSize: safeChunkSize });\n\n const body = onProgress\n ? stream.pipeThrough(\n createProgressStream({ totalFileSize: file.size, onProgress }),\n )\n : stream;\n\n const abortController = new AbortController();\n\n const init: Readonly<RequestInit> = {\n method: \"POST\",\n body,\n duplex: \"half\",\n signal: abortController.signal,\n headers: {\n \"Content-Type\": \"application/octet-stream\",\n ...(customHeaders || {}),\n },\n };\n\n const response = fetch(url, init);\n\n return {\n result: response.then((res) => ({\n ok: res.ok,\n total: file.size,\n message: res.ok ? undefined : `Upload failed with status ${res.status}`,\n status: res.ok ? \"success\" : \"error\",\n })),\n actions: {\n abort: () => abortController.abort(), // Never put an argument when aborting.\n refresh: () => {\n abortController.abort(); // Never put an argument when aborting.\n refresh();\n },\n },\n };\n};\n\nexport default uploadWithStream;\n","export * from \"./types\";\nimport {\n Upload,\n UploadResponse,\n UploadResult,\n OnProgressParams,\n} from \"./types\";\nimport { wait } from \"./utils\";\nimport uploadWithStream from \"./stream/index\";\n\n/**\n * Orchestrates file upload by selecting the optimal method and managing retries and errors.\n * 최적의 업로드 방식을 선택하고 재시도 및 에러 처리를 관리하여 파일 업로드를 수행합니다.\n */\nconst upload = async (\n { url, file, options: { method = \"stream\", ...options } }: Upload,\n retryAttempt = 0,\n): Promise<UploadResponse> => {\n const {\n onComplete,\n onProgress,\n onAbort,\n onRetry,\n onError,\n retryCount: retryCountArg = 3,\n retryDelay = 1000,\n throwOnError = false,\n ...restOptions\n } = options;\n\n const retryCount = retryCountArg;\n\n /**\n * Determines whether to throw an error based on configuration.\n * 구성 설정에 따라 에러를 throw할지 결정합니다.\n */\n const shouldThrowError = (e: unknown): boolean => {\n if (typeof throwOnError === \"function\") {\n return throwOnError(e);\n }\n\n return Boolean(throwOnError);\n };\n\n /**\n * Handles user-triggered aborts.\n * 사용자에 의해 중단된 경우를 처리합니다.\n */\n const handleAbort = (e: DOMException): UploadResult => {\n onAbort?.(e);\n\n if (shouldThrowError(e)) {\n throw e;\n }\n\n return {\n ok: false,\n total: 0,\n message: \"Aborted by user action\",\n status: \"aborted\",\n };\n };\n\n /**\n * Handles generic errors during upload.\n * 업로드 중 발생하는 일반적인 에러를 처리합니다.\n */\n const handleError = (e: Error): UploadResult => {\n onError?.(e);\n\n if (shouldThrowError(e)) {\n throw e;\n }\n\n return { ok: false, total: 0, message: e.message, status: \"error\" };\n };\n\n const finalOptions = {\n ...restOptions,\n onProgress: ({ loaded, total, percentage }: OnProgressParams) => {\n onProgress?.({ loaded, total, percentage });\n\n if (percentage === 100) {\n onComplete?.();\n }\n },\n };\n\n const refresh = () => upload({ url, file, options });\n\n /**\n * Attempts to retry an upload operation.\n * 업로드 작업을 재시도합니다.\n */\n const retryUpload = async (uploadArgs: Upload): Promise<UploadResponse> => {\n const nextRetryAttempt = retryAttempt + 1;\n\n const nextRetryDelay =\n typeof retryDelay === \"function\"\n ? retryDelay(nextRetryAttempt)\n : retryDelay;\n\n await wait(nextRetryDelay);\n\n const uploadResponse = await upload(uploadArgs, nextRetryAttempt);\n\n onRetry?.();\n\n return uploadResponse;\n };\n\n /**\n * Wraps the upload operation with error and retry handling.\n * 에러 처리 및 재시도 로직으로 업로드 작업을 래핑합니다.\n */\n const wrapPromiseErrorHandler = async (\n uploadResponse: UploadResponse,\n ): Promise<UploadResponse> => {\n const { result: originalResult, actions: originalActions } = uploadResponse;\n\n const retriedResult: Promise<UploadResult> = originalResult\n .then((uploadResult) => {\n /**\n * fetch resolves for HTTP 4xx/5xx, so stream mode can return { ok: false, status: 'error' }\n * without rejecting. We rethrow here to route it through retry/onError handling.\n *\n * fetch는 HTTP 4xx/5xx에서도 reject하지 않아 stream 모드가 실패 결과를 resolve로 반환할 수 있습니다.\n * 그래서 여기서 다시 throw해서 retry/onError 흐름으로 태웁니다.\n */\n if (!uploadResult.ok && uploadResult.status === \"error\") {\n throw new Error(uploadResult.message || \"Upload failed\");\n }\n\n return uploadResult;\n })\n .catch(async (e) => {\n if (e instanceof DOMException && e.name === \"AbortError\") {\n return handleAbort(e);\n }\n\n if (retryCount > 0) {\n const { result: retryResult, actions: retryActions } =\n await retryUpload({\n url,\n file,\n options: {\n ...options,\n method,\n retryCount: retryCount - 1,\n },\n });\n\n Object.assign(originalActions, retryActions);\n return retryResult;\n }\n\n return handleError(e as Error);\n });\n\n return { result: Promise.resolve(retriedResult), actions: originalActions };\n };\n\n try {\n const uploadResult = await wrapPromiseErrorHandler(\n await uploadWithStream({\n url,\n file,\n refresh,\n options: finalOptions,\n }),\n );\n\n return uploadResult;\n } catch (e) {\n onError?.(e as Error);\n }\n\n return {\n result: Promise.resolve({\n ok: false,\n total: 0,\n message: \"Unsupported upload method\",\n status: \"error\",\n }),\n actions: {\n abort: () => null,\n refresh,\n },\n };\n};\n\nexport default upload;\n"],"names":["wait"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { U as Upload, d as UploadResponse } from './types-CLZnJDsz.js';
2
+ export { O as OnProgressParams, a as UploadActions, b as UploadOptions, c as UploadParams, e as UploadResult, f as UploadStatus } from './types-CLZnJDsz.js';
3
+
4
+ /**
5
+ * Orchestrates file upload by selecting the optimal method and managing retries and errors.
6
+ * 최적의 업로드 방식을 선택하고 재시도 및 에러 처리를 관리하여 파일 업로드를 수행합니다.
7
+ */
8
+ declare const upload: ({ url, file, options: { method, ...options } }: Upload, retryAttempt?: number) => Promise<UploadResponse>;
9
+
10
+ export { Upload, UploadResponse, upload as default };