@better-s3/react 3.1045.2 → 3.1047.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.
- package/dist/api.d.ts +30 -0
- package/dist/helpers/build-object-key.d.ts +20 -0
- package/dist/helpers/format-eta.d.ts +12 -0
- package/dist/helpers/format-file-size.d.ts +11 -0
- package/dist/helpers/format-speed.d.ts +8 -0
- package/dist/helpers/format-upload-progress.d.ts +17 -0
- package/dist/helpers/get-file-extension.d.ts +13 -0
- package/dist/helpers/index.d.ts +10 -0
- package/dist/helpers/parse-content-disposition.d.ts +18 -0
- package/dist/helpers/speed-tracker.d.ts +17 -0
- package/dist/helpers/truncate-filename.d.ts +9 -0
- package/dist/helpers/validate-file.d.ts +22 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/{use-delete.d.ts → hooks/use-delete.d.ts} +4 -3
- package/dist/{use-download.d.ts → hooks/use-download.d.ts} +5 -10
- package/dist/hooks/use-fetch-download.d.ts +23 -0
- package/dist/hooks/use-multi-upload-controls.d.ts +33 -0
- package/dist/{use-multi-upload.d.ts → hooks/use-multi-upload.d.ts} +4 -3
- package/dist/hooks/use-upload-controls.d.ts +44 -0
- package/dist/hooks/use-upload.d.ts +75 -0
- package/dist/index.d.ts +13 -8
- package/dist/index.js +581 -186
- package/dist/index.js.map +1 -1
- package/dist/internal-helpers.d.ts +9 -0
- package/dist/s3-provider.d.ts +47 -0
- package/dist/store/index.d.ts +3 -0
- package/dist/store/local-storage-store.d.ts +9 -0
- package/dist/store/memory-store.d.ts +14 -0
- package/dist/types/download.d.ts +19 -2
- package/dist/types/error.d.ts +14 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/s3-api.d.ts +158 -0
- package/dist/types/upload-store.d.ts +54 -0
- package/dist/types/upload.d.ts +56 -0
- package/dist/upload/constants.d.ts +1 -1
- package/dist/upload/multipart.d.ts +4 -3
- package/dist/upload/retry.d.ts +2 -1
- package/dist/upload/upload-file.d.ts +5 -1
- package/dist/upload/upload-files.d.ts +1 -1
- package/package.json +3 -6
- package/dist/helpers.d.ts +0 -7
- package/dist/use-fetch-download.d.ts +0 -33
- package/dist/use-upload-controls.d.ts +0 -63
- package/dist/use-upload.d.ts +0 -19
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/helpers.ts","../src/upload/constants.ts","../src/upload/retry.ts","../src/upload/simple.ts","../src/upload/part.ts","../src/upload/multipart.ts","../src/upload/upload-file.ts","../src/upload/upload-files.ts","../src/use-upload.ts","../src/use-multi-upload.ts","../src/use-upload-controls.ts","../src/use-download.ts","../src/use-fetch-download.ts","../src/use-delete.ts"],"names":["INITIAL_PROGRESS","INITIAL_STATE","useState","useRef","useCallback","validateFile"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Parses the filename from a `Content-Disposition` header value.\n * Prefers `filename*` (RFC 5987, full Unicode) over `filename`.\n * Returns `fallback` if no filename is found.\n */\nexport function parseContentDispositionFilename(\n header: string | null,\n fallback: string,\n): string {\n if (!header) return fallback;\n const starMatch = header.match(/filename\\*=UTF-8''([^;,\\s]+)/i);\n if (starMatch) {\n try {\n return decodeURIComponent(starMatch[1]);\n } catch {\n // fall through\n }\n }\n const match = header.match(/filename=\"([^\"]+)\"/i);\n if (match) return match[1];\n return fallback;\n}\n\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 B\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const size = bytes / Math.pow(1024, i);\n return `${size.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;\n}\n","export const DEFAULT_MULTIPART_THRESHOLD = 30 * 1024 * 1024; // 30 MB\nexport const DEFAULT_PART_SIZE = 10 * 1024 * 1024; // 10 MB\nexport const MAX_RETRIES = 3;\nexport const RETRY_BASE_DELAY = 1_000; // ms\nexport const DEFAULT_CONCURRENT_PARTS = 3;\nexport const DEFAULT_CONCURRENT_FILES = 2;\n","import { RETRY_BASE_DELAY } from \"./constants\";\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n retries: number,\n signal?: AbortSignal,\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if ((err as Error).name === \"AbortError\") throw err;\n lastError = err;\n if (attempt < retries) {\n const delay = RETRY_BASE_DELAY * 2 ** attempt;\n await new Promise((r) => setTimeout(r, delay));\n if (signal?.aborted)\n throw new DOMException(\"Upload aborted\", \"AbortError\");\n }\n }\n }\n throw lastError;\n}\n","import type { UploadProgress } from \"../types\";\n\n/**\n * Uploads a file directly to S3 using a presigned POST form.\n *\n * All policy fields (acl, Content-Type, content-length-range, signature, etc.)\n * are embedded in `fields` and must be appended to the FormData **before** the\n * file — this is an S3 requirement. The size constraint is enforced by S3 at\n * the storage layer, so the server never needs to re-validate it.\n */\nexport function uploadSimple(\n file: File,\n url: string,\n fields: Record<string, string>,\n onProgress?: (progress: UploadProgress) => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n const onAbort = () => {\n xhr.abort();\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n xhr.upload.addEventListener(\"progress\", (e) => {\n if (e.lengthComputable) {\n onProgress?.({\n loaded: e.loaded,\n total: e.total,\n percent: Math.round((e.loaded / e.total) * 100),\n });\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (xhr.status >= 200 && xhr.status < 300) {\n onProgress?.({ loaded: file.size, total: file.size, percent: 100 });\n resolve();\n } else {\n reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"Upload failed: network error\"));\n });\n\n xhr.addEventListener(\"abort\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n });\n\n // S3 presigned POST: policy fields must come before the file field.\n const formData = new FormData();\n for (const [k, v] of Object.entries(fields)) {\n formData.append(k, v);\n }\n formData.append(\"file\", file);\n\n xhr.open(\"POST\", url);\n xhr.send(formData);\n });\n}\n\n/**\n * Uploads a file directly to S3 using a presigned PUT URL.\n *\n * Use this when the server is configured with `upload.method = \"put\"` — for\n * example with Cloudflare R2 which does not support presigned POST.\n * The `headers` object must match exactly what was signed on the server\n * (Content-Type, Content-Disposition, x-amz-meta-*, etc.).\n */\nexport function uploadPut(\n file: File,\n url: string,\n headers: Record<string, string>,\n onProgress?: (progress: UploadProgress) => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n const onAbort = () => {\n xhr.abort();\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n xhr.upload.addEventListener(\"progress\", (e) => {\n if (e.lengthComputable) {\n onProgress?.({\n loaded: e.loaded,\n total: e.total,\n percent: Math.round((e.loaded / e.total) * 100),\n });\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (xhr.status >= 200 && xhr.status < 300) {\n onProgress?.({ loaded: file.size, total: file.size, percent: 100 });\n resolve();\n } else {\n reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"Upload failed: network error\"));\n });\n\n xhr.addEventListener(\"abort\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n });\n\n xhr.open(\"PUT\", url);\n for (const [k, v] of Object.entries(headers)) {\n xhr.setRequestHeader(k, v);\n }\n xhr.send(file);\n });\n}\n","export function uploadPart(\n blob: Blob,\n presignedUrl: string,\n partLoaded: { bytes: number },\n totalSize: number,\n reportProgress: () => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n const onAbort = () => {\n xhr.abort();\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n xhr.upload.addEventListener(\"progress\", (e) => {\n if (e.lengthComputable) {\n partLoaded.bytes = e.loaded;\n reportProgress();\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (xhr.status >= 200 && xhr.status < 300) {\n partLoaded.bytes = blob.size;\n reportProgress();\n resolve();\n } else {\n reject(new Error(`Part upload failed: ${xhr.status}`));\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"Part upload failed: network error\"));\n });\n\n xhr.addEventListener(\"abort\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n });\n\n xhr.open(\"PUT\", presignedUrl);\n xhr.send(blob);\n });\n}\n","import type { UploadProgress, UploadRequestOptions } from \"../types\";\nimport type { S3Api } from \"@better-s3/server\";\nimport { MAX_RETRIES } from \"./constants\";\nimport { withRetry } from \"./retry\";\nimport { uploadPart } from \"./part\";\n\nexport async function uploadMultipart(\n api: S3Api,\n file: File,\n objectKey: string,\n partSize: number,\n concurrentParts: number,\n onProgress?: (progress: UploadProgress) => void,\n signal?: AbortSignal,\n requestOptions?: UploadRequestOptions,\n): Promise<string | undefined> {\n const contentType = requestOptions?.contentType ?? file.type;\n const { uploadId, key } = await api.multipart.init({\n key: objectKey,\n contentType,\n fileSize: file.size,\n fileName:\n requestOptions?.fileName !== null\n ? (requestOptions?.fileName ?? file.name)\n : undefined,\n metadata: requestOptions?.metadata,\n bucket: requestOptions?.bucket,\n acl: requestOptions?.acl,\n });\n\n const totalParts = Math.ceil(file.size / partSize);\n const parts: Array<{ partNumber: number }> = [];\n\n const partProgress: Array<{ bytes: number }> = Array.from(\n { length: totalParts },\n () => ({ bytes: 0 }),\n );\n\n const reportProgress = () => {\n const loaded = partProgress.reduce((sum, p) => sum + p.bytes, 0);\n onProgress?.({\n loaded,\n total: file.size,\n percent: Math.round((loaded / file.size) * 100),\n });\n };\n\n try {\n for (\n let batchStart = 0;\n batchStart < totalParts;\n batchStart += concurrentParts\n ) {\n if (signal?.aborted) {\n throw new DOMException(\"Upload aborted\", \"AbortError\");\n }\n\n const batchEnd = Math.min(batchStart + concurrentParts, totalParts);\n const batch: Array<Promise<{ partNumber: number }>> = [];\n\n for (let i = batchStart; i < batchEnd; i++) {\n const start = i * partSize;\n const end = Math.min(start + partSize, file.size);\n const blob = file.slice(start, end);\n const partNumber = i + 1;\n\n batch.push(\n withRetry(\n async () => {\n const { presignedUrl } = await api.multipart.signPart({\n key,\n uploadId,\n partNumber,\n // Pass the exact byte count so the server binds Content-Length\n // into the HMAC signature. S3 will then reject any PUT whose\n // body size differs from blob.size with SignatureDoesNotMatch.\n partSize: blob.size,\n bucket: requestOptions?.bucket,\n });\n\n partProgress[i].bytes = 0;\n\n await uploadPart(\n blob,\n presignedUrl,\n partProgress[i],\n file.size,\n reportProgress,\n signal,\n );\n\n return { partNumber };\n },\n MAX_RETRIES,\n signal,\n ),\n );\n }\n\n const batchResults = await Promise.all(batch);\n parts.push(...batchResults);\n }\n\n parts.sort((a, b) => a.partNumber - b.partNumber);\n\n const result = await api.multipart.complete({\n key,\n uploadId,\n parts,\n bucket: requestOptions?.bucket,\n });\n onProgress?.({ loaded: file.size, total: file.size, percent: 100 });\n return result.eTag;\n } catch (err) {\n api.multipart\n .abort({ key, uploadId, bucket: requestOptions?.bucket })\n .catch(() => {});\n throw err;\n }\n}\n","import type {\n UploadConfig,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n} from \"../types\";\nimport type { S3Api } from \"@better-s3/server\";\nimport {\n DEFAULT_MULTIPART_THRESHOLD,\n DEFAULT_CONCURRENT_PARTS,\n DEFAULT_PART_SIZE,\n MAX_RETRIES,\n} from \"./constants\";\nimport { withRetry } from \"./retry\";\nimport { uploadSimple, uploadPut } from \"./simple\";\nimport { uploadMultipart } from \"./multipart\";\n\nexport type UploadEngineCallbacks = {\n onProgress?: (progress: UploadProgress) => void;\n /** Called when the upload transitions between internal phases. */\n onPhaseChange?: (phase: \"presigning\" | \"uploading\" | \"finalizing\") => void;\n};\n\nexport async function uploadFile(\n api: S3Api,\n file: File,\n objectKey: string,\n config: UploadConfig = {},\n callbacks: UploadEngineCallbacks = {},\n signal?: AbortSignal,\n requestOptions?: UploadRequestOptions,\n): Promise<UploadResult> {\n const threshold = config.multipartThreshold ?? DEFAULT_MULTIPART_THRESHOLD;\n const useMultipart = config.multipart === true && file.size >= threshold;\n const concurrentParts = config.concurrentParts ?? DEFAULT_CONCURRENT_PARTS;\n const contentType = requestOptions?.contentType ?? file.type;\n\n let eTag: string | undefined;\n\n if (useMultipart) {\n callbacks.onPhaseChange?.(\"uploading\");\n eTag = await uploadMultipart(\n api,\n file,\n objectKey,\n DEFAULT_PART_SIZE,\n concurrentParts,\n callbacks.onProgress,\n signal,\n requestOptions,\n );\n } else {\n await withRetry(\n async () => {\n callbacks.onPhaseChange?.(\"presigning\");\n const presign = await api.upload({\n key: objectKey,\n contentType,\n fileSize: file.size,\n fileName:\n requestOptions?.fileName !== null\n ? (requestOptions?.fileName ?? file.name)\n : undefined,\n metadata: requestOptions?.metadata,\n bucket: requestOptions?.bucket,\n acl: requestOptions?.acl,\n });\n callbacks.onPhaseChange?.(\"uploading\");\n if (presign.method === \"put\") {\n await uploadPut(\n file,\n presign.url,\n presign.headers ?? {},\n callbacks.onProgress,\n signal,\n );\n } else {\n await uploadSimple(\n file,\n presign.url,\n presign.fields ?? {},\n callbacks.onProgress,\n signal,\n );\n }\n },\n MAX_RETRIES,\n signal,\n );\n\n callbacks.onPhaseChange?.(\"finalizing\");\n const confirmed = await api.confirm({\n key: objectKey,\n bucket: requestOptions?.bucket,\n });\n eTag = confirmed.eTag;\n }\n\n return { key: objectKey, eTag };\n}\n","import type {\n UploadConfig,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n} from \"../types\";\nimport type { S3Api } from \"@better-s3/server\";\nimport { DEFAULT_CONCURRENT_FILES } from \"./constants\";\nimport { uploadFile } from \"./upload-file\";\n\nexport type FileItemStatus = \"pending\" | \"uploading\" | \"success\" | \"error\";\n\nexport type FileItem = {\n id: string;\n file: File;\n objectKey: string;\n status: FileItemStatus;\n progress: UploadProgress;\n result: UploadResult | null;\n error: string | null;\n};\n\nexport type MultiUploadCallbacks = {\n onFileProgress?: (id: string, progress: UploadProgress) => void;\n onFileSuccess?: (id: string, result: UploadResult) => void;\n onFileError?: (id: string, error: string) => void;\n onTotalProgress?: (progress: UploadProgress) => void;\n};\n\nexport async function uploadFiles(\n api: S3Api,\n items: Array<{ id: string; file: File; objectKey: string }>,\n config: UploadConfig = {},\n callbacks: MultiUploadCallbacks = {},\n signal?: AbortSignal,\n getRequestOptions?: (file: File) => UploadRequestOptions,\n): Promise<FileItem[]> {\n const results: FileItem[] = items.map((item) => ({\n ...item,\n status: \"pending\" as FileItemStatus,\n progress: { loaded: 0, total: item.file.size, percent: 0 },\n result: null,\n error: null,\n }));\n\n const reportTotalProgress = () => {\n const loaded = results.reduce((sum, r) => sum + r.progress.loaded, 0);\n const total = results.reduce((sum, r) => sum + r.progress.total, 0);\n callbacks.onTotalProgress?.({\n loaded,\n total,\n percent: total > 0 ? Math.round((loaded / total) * 100) : 0,\n });\n };\n\n let nextIndex = 0;\n\n const processNext = async (): Promise<void> => {\n while (nextIndex < results.length) {\n if (signal?.aborted) return;\n const idx = nextIndex++;\n const item = results[idx];\n\n item.status = \"uploading\";\n\n try {\n const result = await uploadFile(\n api,\n item.file,\n item.objectKey,\n config,\n {\n onProgress: (progress) => {\n item.progress = progress;\n callbacks.onFileProgress?.(item.id, progress);\n reportTotalProgress();\n },\n },\n signal,\n getRequestOptions?.(item.file),\n );\n item.status = \"success\";\n item.result = result;\n item.progress = {\n loaded: item.file.size,\n total: item.file.size,\n percent: 100,\n };\n callbacks.onFileSuccess?.(item.id, result);\n reportTotalProgress();\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n item.status = \"error\";\n item.error = \"Upload cancelled\";\n return;\n }\n const message = err instanceof Error ? err.message : \"Upload failed\";\n item.status = \"error\";\n item.error = message;\n callbacks.onFileError?.(item.id, message);\n reportTotalProgress();\n }\n }\n };\n\n const concurrentFiles = config.concurrentFiles ?? DEFAULT_CONCURRENT_FILES;\n const workers = Array.from(\n { length: Math.min(concurrentFiles, items.length) },\n () => processNext(),\n );\n await Promise.all(workers);\n\n return results;\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\nimport type { S3Api } from \"@better-s3/server\";\nimport { validateFile } from \"@better-s3/server\";\nimport type {\n UploadConfig,\n UploadHooks,\n UploadPhase,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n} from \"./types\";\nimport { uploadFile } from \"./upload\";\n\nexport type UseUploadOptions = UploadConfig &\n UploadHooks & {\n api: S3Api;\n };\n\nexport type UseUploadState = {\n phase: UploadPhase;\n progress: UploadProgress;\n error: string | null;\n result: UploadResult | null;\n fileName: string | null;\n fileSize: number | null;\n};\n\nexport type UseUploadReturn = UseUploadState & {\n upload: (\n file: File,\n objectKey: string,\n requestOptions?: UploadRequestOptions,\n ) => Promise<void>;\n cancel: () => void;\n reset: () => void;\n};\n\nconst INITIAL_PROGRESS: UploadProgress = { loaded: 0, total: 0, percent: 0 };\n\nconst INITIAL_STATE: UseUploadState = {\n phase: \"idle\",\n progress: INITIAL_PROGRESS,\n error: null,\n result: null,\n fileName: null,\n fileSize: null,\n};\n\nexport function useUpload(options: UseUploadOptions): UseUploadReturn {\n const [state, setState] = useState<UseUploadState>(INITIAL_STATE);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const abortRef = useRef<AbortController | null>(null);\n\n const upload = useCallback(\n async (\n file: File,\n objectKey: string,\n requestOptions?: UploadRequestOptions,\n ) => {\n setState({\n ...INITIAL_STATE,\n phase: \"validating\",\n fileName: file.name,\n fileSize: file.size,\n });\n const opts = optionsRef.current;\n\n const validationError = validateFile(file, {\n accept: opts.accept,\n maxFileSize: opts.maxFileSize,\n });\n if (validationError) {\n setState((s) => ({ ...s, phase: \"error\", error: validationError }));\n opts.onError?.(file, new Error(validationError), \"validating\");\n return;\n }\n\n if (opts.beforeUpload) {\n const allowed = await opts.beforeUpload(file);\n if (!allowed) {\n setState((s) => ({\n ...s,\n phase: \"error\",\n error: \"Upload blocked by beforeUpload hook\",\n }));\n opts.onError?.(file, new Error(\"blocked\"), \"validating\");\n return;\n }\n }\n\n setState((s) => ({ ...s, phase: \"presigning\" }));\n opts.onUploadStart?.(file, objectKey);\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n try {\n const result = await uploadFile(\n opts.api,\n file,\n objectKey,\n {\n multipart: opts.multipart,\n multipartThreshold: opts.multipartThreshold,\n concurrentParts: opts.concurrentParts,\n },\n {\n onProgress: (progress) => {\n setState((s) => ({ ...s, progress }));\n opts.onProgress?.(file, progress);\n },\n onPhaseChange: (phase) => setState((s) => ({ ...s, phase })),\n },\n controller.signal,\n requestOptions,\n );\n\n setState((s) => ({\n ...s,\n phase: \"success\",\n result,\n progress: { loaded: file.size, total: file.size, percent: 100 },\n }));\n await opts.onSuccess?.(file, result);\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n opts.onCancel?.(file);\n setState(INITIAL_STATE);\n return;\n }\n const message = err instanceof Error ? err.message : \"Upload failed\";\n setState((s) => ({ ...s, phase: \"error\", error: message }));\n opts.onError?.(file, err, \"uploading\");\n } finally {\n abortRef.current = null;\n }\n },\n [],\n );\n\n const cancel = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n return { ...state, upload, cancel, reset };\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\nimport type { S3Api } from \"@better-s3/server\";\nimport { validateFile } from \"@better-s3/server\";\nimport type {\n UploadConfig,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n MultiUploadPhase,\n MultiUploadFileState,\n MultiUploadHooks,\n} from \"./types\";\nimport { uploadFiles } from \"./upload\";\n\nexport type UseMultiUploadOptions = UploadConfig &\n MultiUploadHooks & {\n api: S3Api;\n /** Static request options applied to all files */\n uploadOptions?: UploadRequestOptions;\n /** Per-file request options (overrides uploadOptions) */\n getUploadOptions?: (file: File) => UploadRequestOptions;\n };\n\nexport type UseMultiUploadState = {\n phase: MultiUploadPhase;\n files: MultiUploadFileState[];\n totalProgress: UploadProgress;\n error: string | null;\n};\n\nexport type UseMultiUploadReturn = UseMultiUploadState & {\n upload: (files: File[], resolveKey: (file: File) => string) => Promise<void>;\n cancel: () => void;\n reset: () => void;\n};\n\nconst INITIAL_PROGRESS: UploadProgress = { loaded: 0, total: 0, percent: 0 };\n\nconst INITIAL_STATE: UseMultiUploadState = {\n phase: \"idle\",\n files: [],\n totalProgress: INITIAL_PROGRESS,\n error: null,\n};\n\nlet nextId = 0;\nfunction generateId() {\n return `file-${++nextId}`;\n}\n\nexport function useMultiUpload(\n options: UseMultiUploadOptions,\n): UseMultiUploadReturn {\n const [state, setState] = useState<UseMultiUploadState>(INITIAL_STATE);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const abortRef = useRef<AbortController | null>(null);\n const fileMapRef = useRef<Map<string, File>>(new Map());\n\n const upload = useCallback(\n async (files: File[], resolveKey: (file: File) => string) => {\n const opts = optionsRef.current;\n\n const items: Array<{\n id: string;\n file: File;\n objectKey: string;\n }> = [];\n const fileStates: MultiUploadFileState[] = [];\n const fileMap = new Map<string, File>();\n\n setState((s) => ({ ...s, phase: \"validating\", error: null }));\n\n if (opts.maxFiles && files.length > opts.maxFiles) {\n const msg = `Too many files. Maximum is ${opts.maxFiles}.`;\n setState((s) => ({ ...s, phase: \"error\", error: msg }));\n opts.onError?.(new Error(msg));\n return;\n }\n\n for (const file of files) {\n const validationError = validateFile(file, {\n accept: opts.accept,\n maxFileSize: opts.maxFileSize,\n });\n if (validationError) {\n const msg = `${file.name}: ${validationError}`;\n setState((s) => ({ ...s, phase: \"error\", error: msg }));\n opts.onError?.(new Error(msg));\n return;\n }\n }\n\n if (opts.beforeUpload) {\n const allowed = await opts.beforeUpload(files);\n if (!allowed) {\n setState((s) => ({\n ...s,\n phase: \"error\",\n error: \"Upload blocked by beforeUpload hook\",\n }));\n opts.onError?.(new Error(\"blocked\"));\n return;\n }\n }\n\n for (const file of files) {\n const id = generateId();\n const objectKey = resolveKey(file);\n items.push({ id, file, objectKey });\n fileMap.set(id, file);\n fileStates.push({\n id,\n fileName: file.name,\n fileSize: file.size,\n status: \"pending\",\n progress: { loaded: 0, total: file.size, percent: 0 },\n error: null,\n });\n }\n\n fileMapRef.current = fileMap;\n\n setState({\n phase: \"uploading\",\n files: fileStates,\n totalProgress: {\n loaded: 0,\n total: files.reduce((s, f) => s + f.size, 0),\n percent: 0,\n },\n error: null,\n });\n\n opts.onUploadStart?.(files);\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n try {\n const results = await uploadFiles(\n opts.api,\n items,\n {\n multipart: opts.multipart,\n multipartThreshold: opts.multipartThreshold,\n concurrentParts: opts.concurrentParts,\n concurrentFiles: opts.concurrentFiles,\n },\n {\n onFileProgress: (id, progress) => {\n setState((s) => ({\n ...s,\n files: s.files.map((f) =>\n f.id === id ? { ...f, status: \"uploading\", progress } : f,\n ),\n }));\n const file = fileMap.get(id);\n if (file) opts.onFileProgress?.(file, progress);\n },\n onFileSuccess: (id, result) => {\n setState((s) => ({\n ...s,\n files: s.files.map((f) =>\n f.id === id\n ? {\n ...f,\n status: \"success\",\n progress: {\n loaded: f.fileSize,\n total: f.fileSize,\n percent: 100,\n },\n }\n : f,\n ),\n }));\n const file = fileMap.get(id);\n if (file) opts.onFileSuccess?.(file, result);\n },\n onFileError: (id, error) => {\n setState((s) => ({\n ...s,\n files: s.files.map((f) =>\n f.id === id ? { ...f, status: \"error\", error } : f,\n ),\n }));\n const file = fileMap.get(id);\n if (file) opts.onFileError?.(file, error);\n },\n onTotalProgress: (progress) => {\n setState((s) => ({ ...s, totalProgress: progress }));\n opts.onProgress?.(progress);\n },\n },\n controller.signal,\n (file) => {\n const perFile = opts.getUploadOptions?.(file);\n if (!opts.uploadOptions) return perFile ?? {};\n return { ...opts.uploadOptions, ...perFile };\n },\n );\n\n const hasErrors = results.some((r) => r.status === \"error\");\n const successResults = results\n .filter((r) => r.result !== null)\n .map((r) => r.result!);\n\n setState((s) => ({\n ...s,\n phase: hasErrors ? \"error\" : \"success\",\n error: hasErrors\n ? `${results.filter((r) => r.status === \"error\").length} file(s) failed`\n : null,\n totalProgress: hasErrors\n ? s.totalProgress\n : {\n loaded: s.totalProgress.total,\n total: s.totalProgress.total,\n percent: 100,\n },\n }));\n\n if (!hasErrors) {\n await opts.onSuccess?.(successResults);\n }\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n opts.onCancel?.();\n setState(INITIAL_STATE);\n return;\n }\n const message = err instanceof Error ? err.message : \"Upload failed\";\n setState((s) => ({ ...s, phase: \"error\", error: message }));\n opts.onError?.(err);\n } finally {\n abortRef.current = null;\n }\n },\n [],\n );\n\n const cancel = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n return { ...state, upload, cancel, reset };\n}\n","\"use client\";\n\nimport { useRef, useState } from \"react\";\nimport type {\n UploadPhase,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n MultiUploadFileState,\n MultiUploadPhase,\n} from \"./types\";\nimport { useUpload, type UseUploadOptions } from \"./use-upload\";\nimport { useMultiUpload, type UseMultiUploadOptions } from \"./use-multi-upload\";\nimport type { S3Api } from \"@better-s3/server\";\nimport type { UploadConfig } from \"./types\";\n\nconst INITIAL_PROGRESS: UploadProgress = { loaded: 0, total: 0, percent: 0 };\n\nexport type UseUploadControlsOptions = UploadConfig & {\n api: S3Api;\n objectKey: string | ((file: File) => string);\n /**\n * Maximum number of files. When > 1 the hook switches to multi-upload mode\n * and the native file picker allows selecting multiple files.\n * @default 1\n */\n maxFiles?: number;\n /** Static request options applied to all files (multi mode) */\n uploadOptions?: UploadRequestOptions;\n /** Per-file request options */\n getUploadOptions?: (file: File) => UploadRequestOptions;\n // Callbacks – typed as a union to support both single and multi modes\n beforeUpload?:\n | ((file: File) => boolean | Promise<boolean>)\n | ((files: File[]) => boolean | Promise<boolean>);\n onUploadStart?:\n | ((file: File, key: string) => void)\n | ((files: File[]) => void);\n onProgress?:\n | ((file: File, progress: UploadProgress) => void)\n | ((progress: UploadProgress) => void);\n onSuccess?:\n | ((file: File, result: UploadResult) => void | Promise<void>)\n | ((results: UploadResult[]) => void | Promise<void>);\n onError?:\n | ((file: File | null, error: unknown, phase: UploadPhase) => void)\n | ((error: unknown) => void);\n onCancel?: ((file: File | null) => void) | (() => void);\n // Multi-only callbacks\n onFileProgress?: (file: File, progress: UploadProgress) => void;\n onFileSuccess?: (file: File, result: UploadResult) => void;\n onFileError?: (file: File, error: string) => void;\n};\n\nexport type UseUploadControlsReturn = {\n /** Whether the hook is in single-file or multi-file mode */\n mode: \"single\" | \"multi\";\n phase: UploadPhase | MultiUploadPhase;\n /** Info about the selected file (single mode only) */\n fileInfo: { name: string; size: number } | null;\n /** Upload progress (single mode) */\n progress: UploadProgress;\n /** Per-file states (multi mode only) */\n files: MultiUploadFileState[];\n /** Aggregated progress across all files (multi mode) */\n totalProgress: UploadProgress;\n error: string | null;\n isUploading: boolean;\n handleFiles: (files: FileList | null) => void;\n openFilePicker: () => void;\n cancel: () => void;\n reset: () => void;\n /** Spread on a hidden `<input>` element */\n inputProps: {\n ref: React.RefObject<HTMLInputElement | null>;\n type: \"file\";\n multiple?: true;\n accept?: string;\n hidden: true;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n };\n /** Spread on a container to enable drag-and-drop */\n dropHandlers: {\n onDragOver: (e: React.DragEvent) => void;\n onDrop: (e: React.DragEvent) => void;\n };\n};\n\nexport function useUploadControls(\n options: UseUploadControlsOptions,\n): UseUploadControlsReturn {\n const isMulti = (options.maxFiles ?? 1) > 1;\n\n // Build per-mode options. Both hooks are called unconditionally (React rules).\n const singleOpts: UseUploadOptions = {\n api: options.api,\n accept: options.accept,\n maxFileSize: options.maxFileSize,\n multipart: options.multipart,\n multipartThreshold: options.multipartThreshold,\n concurrentParts: options.concurrentParts,\n beforeUpload: options.beforeUpload as UseUploadOptions[\"beforeUpload\"],\n onUploadStart: options.onUploadStart as UseUploadOptions[\"onUploadStart\"],\n onProgress: options.onProgress as UseUploadOptions[\"onProgress\"],\n onSuccess: options.onSuccess as UseUploadOptions[\"onSuccess\"],\n onError: options.onError as UseUploadOptions[\"onError\"],\n onCancel: options.onCancel as UseUploadOptions[\"onCancel\"],\n };\n\n const multiOpts: UseMultiUploadOptions = {\n api: options.api,\n accept: options.accept,\n maxFileSize: options.maxFileSize,\n maxFiles: options.maxFiles,\n multipart: options.multipart,\n multipartThreshold: options.multipartThreshold,\n concurrentParts: options.concurrentParts,\n concurrentFiles: options.concurrentFiles,\n uploadOptions: options.uploadOptions,\n getUploadOptions: options.getUploadOptions,\n beforeUpload: options.beforeUpload as UseMultiUploadOptions[\"beforeUpload\"],\n onUploadStart:\n options.onUploadStart as UseMultiUploadOptions[\"onUploadStart\"],\n onProgress: options.onProgress as UseMultiUploadOptions[\"onProgress\"],\n onSuccess: options.onSuccess as UseMultiUploadOptions[\"onSuccess\"],\n onError: options.onError as UseMultiUploadOptions[\"onError\"],\n onCancel: options.onCancel as UseMultiUploadOptions[\"onCancel\"],\n onFileProgress: options.onFileProgress,\n onFileSuccess: options.onFileSuccess,\n onFileError: options.onFileError,\n };\n\n const single = useUpload(singleOpts);\n const multi = useMultiUpload(multiOpts);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const [fileInfo, setFileInfo] = useState<{\n name: string;\n size: number;\n } | null>(null);\n\n const resolveKey = (file: File): string =>\n typeof options.objectKey === \"function\"\n ? options.objectKey(file)\n : options.objectKey;\n\n const handleFiles = async (files: FileList | null) => {\n if (isMulti) {\n if (!files?.length) return;\n await multi.upload(Array.from(files), resolveKey);\n } else {\n const file = files?.[0];\n if (!file) return;\n setFileInfo({ name: file.name, size: file.size });\n await single.upload(file, resolveKey(file), {\n ...options.uploadOptions,\n ...options.getUploadOptions?.(file),\n });\n }\n };\n\n const openFilePicker = () => inputRef.current?.click();\n const isUploading = isMulti\n ? multi.phase === \"uploading\"\n : single.phase === \"uploading\";\n\n return {\n mode: isMulti ? \"multi\" : \"single\",\n phase: isMulti ? multi.phase : single.phase,\n fileInfo: isMulti ? null : fileInfo,\n progress: isMulti ? INITIAL_PROGRESS : single.progress,\n files: isMulti ? multi.files : [],\n totalProgress: isMulti ? multi.totalProgress : INITIAL_PROGRESS,\n error: isMulti ? multi.error : single.error,\n isUploading,\n handleFiles,\n openFilePicker,\n cancel: isMulti ? multi.cancel : single.cancel,\n reset: isMulti\n ? multi.reset\n : () => {\n single.reset();\n setFileInfo(null);\n },\n inputProps: {\n ref: inputRef,\n type: \"file\",\n ...(isMulti && { multiple: true as const }),\n accept: options.accept?.join(\",\"),\n hidden: true,\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => {\n handleFiles(e.target.files);\n e.target.value = \"\";\n },\n },\n dropHandlers: {\n onDragOver: (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n },\n onDrop: (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (!isUploading) handleFiles(e.dataTransfer.files);\n },\n },\n };\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\nimport type { S3Api } from \"@better-s3/server\";\n\n/** \"presigning\" = fetching the presigned URL from the server; download itself is native */\nexport type DownloadPhase = \"idle\" | \"presigning\" | \"error\";\n\nexport type DownloadHooks = {\n beforeDownload?: (key: string) => Promise<boolean> | boolean;\n /** Fires as soon as the browser has been handed the URL — not when download completes. */\n onInitiated?: (key: string) => void;\n onError?: (key: string, error: unknown) => void;\n};\n\nexport type UseDownloadOptions = DownloadHooks & {\n api: S3Api;\n /** Target bucket (overrides server default) */\n bucket?: string;\n};\n\nexport type UseDownloadState = {\n phase: DownloadPhase;\n error: string | null;\n /** Presigned URL — set after a successful presign, cleared on reset */\n url: string | null;\n /** Validity window in seconds for the presigned URL */\n expiresIn: number | null;\n};\n\nexport type UseDownloadReturn = UseDownloadState & {\n download: (key: string, downloadName?: string) => Promise<void>;\n /** Fetch the presigned URL without triggering a browser download — for headless use */\n presign: (\n key: string,\n downloadName?: string,\n ) => Promise<{ url: string; expiresIn: number } | null>;\n reset: () => void;\n};\n\nconst INITIAL_STATE: UseDownloadState = {\n phase: \"idle\",\n error: null,\n url: null,\n expiresIn: null,\n};\n\nexport function useDownload(options: UseDownloadOptions): UseDownloadReturn {\n const [state, setState] = useState<UseDownloadState>(INITIAL_STATE);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const presign = useCallback(async (key: string, downloadName?: string) => {\n const opts = optionsRef.current;\n setState({ phase: \"presigning\", error: null, url: null, expiresIn: null });\n try {\n const result = await opts.api.download(key, {\n fileName: downloadName,\n bucket: opts.bucket,\n });\n setState({\n phase: \"idle\",\n error: null,\n url: result.url,\n expiresIn: result.expiresIn,\n });\n return { url: result.url, expiresIn: result.expiresIn };\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Download failed\";\n setState({ phase: \"error\", error: message, url: null, expiresIn: null });\n opts.onError?.(key, err);\n return null;\n }\n }, []);\n\n const download = useCallback(\n async (key: string, downloadName?: string) => {\n const opts = optionsRef.current;\n\n if (opts.beforeDownload) {\n const allowed = await opts.beforeDownload(key);\n if (!allowed) {\n setState({\n phase: \"error\",\n error: \"Download blocked by beforeDownload hook\",\n url: null,\n expiresIn: null,\n });\n opts.onError?.(key, new Error(\"blocked\"));\n return;\n }\n }\n\n const result = await presign(key, downloadName);\n if (!result) return; // presign already set error state\n\n // Native browser download via location — server sets Content-Disposition: attachment.\n window.location.href = result.url;\n\n opts.onInitiated?.(key);\n },\n [presign],\n );\n\n const reset = useCallback(() => {\n setState(INITIAL_STATE);\n }, []);\n\n return { ...state, download, presign, reset };\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\nimport type { S3Api } from \"@better-s3/server\";\nimport { parseContentDispositionFilename } from \"./helpers\";\n\nexport type FetchDownloadPhase =\n | \"idle\"\n | \"presigning\"\n | \"downloading\"\n | \"success\"\n | \"error\";\n\nexport type FetchDownloadProgress = {\n loaded: number;\n total: number;\n percent: number;\n};\n\nexport type FetchDownloadHooks = {\n beforeDownload?: (key: string) => Promise<boolean> | boolean;\n onDownloadStart?: (key: string) => void;\n onProgress?: (key: string, progress: FetchDownloadProgress) => void;\n onSuccess?: (key: string, fileName: string) => Promise<void> | void;\n onError?: (key: string, error: unknown, phase: FetchDownloadPhase) => void;\n onCancel?: (key: string) => void;\n};\n\nexport type UseFetchDownloadOptions = FetchDownloadHooks & {\n api: S3Api;\n /** Target bucket (overrides server default) */\n bucket?: string;\n};\n\nexport type UseFetchDownloadState = {\n phase: FetchDownloadPhase;\n progress: FetchDownloadProgress;\n error: string | null;\n fileName: string | null;\n fileSize: number | null;\n};\n\nexport type UseFetchDownloadReturn = UseFetchDownloadState & {\n download: (key: string, downloadName?: string) => Promise<void>;\n cancel: () => void;\n reset: () => void;\n};\n\nconst INITIAL_PROGRESS: FetchDownloadProgress = {\n loaded: 0,\n total: 0,\n percent: 0,\n};\n\nconst INITIAL_STATE: UseFetchDownloadState = {\n phase: \"idle\",\n progress: INITIAL_PROGRESS,\n error: null,\n fileName: null,\n fileSize: null,\n};\n\nexport function useFetchDownload(\n options: UseFetchDownloadOptions,\n): UseFetchDownloadReturn {\n const [state, setState] = useState<UseFetchDownloadState>(INITIAL_STATE);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const abortRef = useRef<AbortController | null>(null);\n\n const download = useCallback(async (key: string, downloadName?: string) => {\n const fallback = key.split(\"/\").pop() ?? key;\n const opts = optionsRef.current;\n\n if (opts.beforeDownload) {\n const allowed = await opts.beforeDownload(key);\n if (!allowed) {\n setState((s) => ({\n ...s,\n phase: \"error\",\n error: \"Download blocked by beforeDownload hook\",\n }));\n opts.onError?.(key, new Error(\"blocked\"), \"presigning\");\n return;\n }\n }\n\n setState({\n phase: \"presigning\",\n progress: INITIAL_PROGRESS,\n error: null,\n fileName: downloadName ?? null,\n fileSize: null,\n });\n\n try {\n const { url } = await opts.api.download(key, {\n fileName: downloadName,\n bucket: opts.bucket,\n });\n\n setState((s) => ({ ...s, phase: \"downloading\" }));\n opts.onDownloadStart?.(key);\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n const res = await fetch(url, { signal: controller.signal });\n if (!res.ok) {\n throw new Error(\n res.status === 404\n ? \"File not found\"\n : `Download failed (${res.status})`,\n );\n }\n\n const contentLength = Number(res.headers.get(\"content-length\") || 0);\n const name =\n downloadName ??\n parseContentDispositionFilename(\n res.headers.get(\"content-disposition\"),\n fallback,\n );\n setState((s) => ({\n ...s,\n fileName: name,\n fileSize: contentLength || null,\n }));\n\n const reader = res.body?.getReader();\n if (!reader) throw new Error(\"ReadableStream not supported\");\n\n const chunks: BlobPart[] = [];\n let loaded = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n loaded += value.byteLength;\n const percent =\n contentLength > 0 ? Math.round((loaded / contentLength) * 100) : 0;\n const progress: FetchDownloadProgress = {\n loaded,\n total: contentLength,\n percent,\n };\n setState((s) => ({ ...s, progress }));\n opts.onProgress?.(key, progress);\n }\n\n const blob = new Blob(chunks);\n const blobUrl = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = blobUrl;\n anchor.download = name ?? fallback;\n anchor.click();\n URL.revokeObjectURL(blobUrl);\n\n setState((s) => ({\n ...s,\n phase: \"success\",\n fileSize: blob.size,\n progress: { loaded: blob.size, total: blob.size, percent: 100 },\n }));\n await opts.onSuccess?.(key, name ?? fallback);\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n opts.onCancel?.(key);\n setState(INITIAL_STATE);\n return;\n }\n const message = err instanceof Error ? err.message : \"Download failed\";\n setState((s) => ({ ...s, phase: \"error\", error: message }));\n opts.onError?.(key, err, \"downloading\");\n } finally {\n abortRef.current = null;\n }\n }, []);\n\n const cancel = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n return { ...state, download, cancel, reset };\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\nimport type { S3Api } from \"@better-s3/server\";\nimport type { DeletePhase, DeleteHooks } from \"./types\";\n\nexport type UseDeleteOptions = DeleteHooks & {\n api: S3Api;\n /** Target bucket (overrides server default) */\n bucket?: string;\n};\n\nexport type UseDeleteState = {\n phase: DeletePhase;\n error: string | null;\n};\n\nexport type UseDeleteReturn = UseDeleteState & {\n requestDelete: (key: string) => void;\n confirmDelete: () => Promise<void>;\n cancelDelete: () => void;\n reset: () => void;\n pendingKey: string | null;\n};\n\nconst INITIAL_STATE: UseDeleteState = {\n phase: \"idle\",\n error: null,\n};\n\nexport function useDelete(options: UseDeleteOptions): UseDeleteReturn {\n const [state, setState] = useState<UseDeleteState>(INITIAL_STATE);\n const [pendingKey, setPendingKey] = useState<string | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const requestDelete = useCallback((key: string) => {\n setPendingKey(key);\n setState({ phase: \"confirming\", error: null });\n }, []);\n\n const confirmDelete = useCallback(async () => {\n if (!pendingKey) return;\n const opts = optionsRef.current;\n\n if (opts.beforeDelete) {\n const allowed = await opts.beforeDelete(pendingKey);\n if (!allowed) {\n setState({\n phase: \"error\",\n error: \"Delete blocked by beforeDelete hook\",\n });\n opts.onError?.(pendingKey, new Error(\"blocked\"), \"confirming\");\n setPendingKey(null);\n return;\n }\n }\n\n setState({ phase: \"deleting\", error: null });\n opts.onDeleteStart?.(pendingKey);\n\n try {\n await opts.api.delete(pendingKey, { bucket: opts.bucket });\n\n setState({ phase: \"success\", error: null });\n await opts.onSuccess?.(pendingKey);\n setPendingKey(null);\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Delete failed\";\n setState({ phase: \"error\", error: message });\n opts.onError?.(pendingKey, err, \"deleting\");\n }\n }, [pendingKey]);\n\n const cancelDelete = useCallback(() => {\n setPendingKey(null);\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n setPendingKey(null);\n setState(INITIAL_STATE);\n }, []);\n\n return {\n ...state,\n pendingKey,\n requestDelete,\n confirmDelete,\n cancelDelete,\n reset,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/error.ts","../src/api.ts","../src/s3-provider.tsx","../src/store/local-storage-store.ts","../src/store/memory-store.ts","../src/upload/constants.ts","../src/upload/retry.ts","../src/upload/simple.ts","../src/upload/part.ts","../src/upload/multipart.ts","../src/upload/upload-file.ts","../src/upload/upload-files.ts","../src/helpers/format-file-size.ts","../src/helpers/validate-file.ts","../src/helpers/parse-content-disposition.ts","../src/helpers/format-upload-progress.ts","../src/helpers/format-speed.ts","../src/helpers/format-eta.ts","../src/helpers/build-object-key.ts","../src/helpers/get-file-extension.ts","../src/helpers/truncate-filename.ts","../src/helpers/speed-tracker.ts","../src/internal-helpers.ts","../src/hooks/use-upload.ts","../src/hooks/use-multi-upload.ts","../src/hooks/use-upload-controls.ts","../src/hooks/use-multi-upload-controls.ts","../src/hooks/use-download.ts","../src/hooks/use-fetch-download.ts","../src/hooks/use-delete.ts"],"names":["parts","useContext","useRef","INITIAL_PROGRESS","INITIAL_STATE","useState","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["import type { UploadPhase } from \"./upload\";\n\n/**\n * Structured error thrown by the upload engine.\n *\n * - `code` — machine-readable error code (e.g. `\"VALIDATION_ERROR\"`, `\"NETWORK_ERROR\"`)\n * - `statusCode` — HTTP status code when the error originated from a server response\n * - `phase` — upload phase in which the error occurred\n */\nexport class S3UploadError extends Error {\n readonly code: string;\n readonly statusCode: number | undefined;\n readonly phase: UploadPhase | undefined;\n\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n phase?: UploadPhase,\n ) {\n super(message);\n this.name = \"S3UploadError\";\n this.code = code;\n this.statusCode = statusCode;\n this.phase = phase;\n }\n}\n","/**\n * Client-side factory for the better-s3 presign API.\n *\n * Accepts an `S3Api` object — implement each method to call your own backend\n * endpoint, tRPC mutation, GraphQL query, or anything else. The object is\n * returned as-is; `createS3Client` just enforces the type contract.\n *\n * If you are using `@better-s3/server`, use `createS3Api` from that package\n * instead — it builds a standard fetch client from a base path.\n *\n * @example\n * ```ts\n * import { createS3Client } from \"@better-s3/react\";\n *\n * export const s3Client = createS3Client({\n * async upload(payload) {\n * return fetch(\"/api/storage/presign\", { method: \"POST\", body: JSON.stringify(payload) })\n * .then(r => r.json());\n * },\n * async confirm(payload) { ... },\n * async download(key, options) { ... },\n * async delete(key) { ... },\n * multipart: { init, signPart, listParts, complete, abort },\n * });\n * ```\n */\nimport type {\n S3Api,\n} from \"./types/s3-api\";\n\nexport function createS3Client(input: S3Api): S3Api {\n return input;\n}\n\n/** @deprecated Use {@link createS3Client} instead. */\nexport const createS3Api = createS3Client;\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { S3Api } from \"./types/s3-api\";\n\n/**\n * Internal context — use `S3Provider` to supply and `useS3Client` to consume.\n * Exported so hooks can call `useContext(S3Context)` directly without throwing\n * when `api` is passed explicitly.\n */\nexport const S3Context = createContext<S3Api | null>(null);\n\n/**\n * Provides an `S3Api` client to all child hooks and UI components.\n *\n * Wrap your app (or a sub-tree) once; hooks no longer need `api` passed\n * individually.\n *\n * @example\n * ```tsx\n * // With @better-s3/server:\n * import { createS3Api } from \"@better-s3/server\";\n * import { S3Provider } from \"@better-s3/react\";\n *\n * const s3Client = createS3Api(\"/api/s3\");\n *\n * export function Providers({ children }: { children: React.ReactNode }) {\n * return <S3Provider client={s3Client}>{children}</S3Provider>;\n * }\n *\n * // With a custom server (use createS3Client for a compatible fetch client):\n * import { createS3Client, S3Provider } from \"@better-s3/react\";\n *\n * const s3Client = createS3Client(\"/api/my-s3\");\n *\n * export function Providers({ children }: { children: React.ReactNode }) {\n * return <S3Provider client={s3Client}>{children}</S3Provider>;\n * }\n * ```\n */\nexport function S3Provider({\n client,\n children,\n}: {\n client: S3Api;\n children: ReactNode;\n}) {\n return <S3Context.Provider value={client}>{children}</S3Context.Provider>;\n}\n\n/**\n * Returns the `S3Api` client from the nearest `S3Provider`.\n * Throws if called outside a provider and no `api` prop was given to the hook.\n *\n * @throws if no `S3Provider` is found in the tree.\n */\nexport function useS3Client(): S3Api {\n const ctx = useContext(S3Context);\n if (!ctx) {\n throw new Error(\n \"[better-s3] No S3Api client found. \" +\n \"Either wrap your app with <S3Provider client={...}> or pass `api` directly to the hook.\",\n );\n }\n return ctx;\n}\n","import type { StoredUpload, UploadStore } from \"../types/upload-store\";\n\nconst STORAGE_PREFIX = \"better-s3:upload:\";\n\n/**\n * Default `UploadStore` implementation backed by `localStorage`.\n * Stores one pending upload per S3 object key.\n *\n * Falls back silently when `localStorage` is unavailable (SSR, private\n * browsing with full quota, or environments without a `window` object).\n */\nexport function createLocalStorageStore(): UploadStore {\n return {\n get(key, fileSize) {\n try {\n const raw = localStorage.getItem(STORAGE_PREFIX + key);\n if (!raw) return null;\n const stored = JSON.parse(raw) as StoredUpload;\n // Reject if the stored size doesn't match — different file for the same key.\n return stored.fileSize === fileSize ? stored : null;\n } catch {\n return null;\n }\n },\n\n set(upload) {\n try {\n localStorage.setItem(\n STORAGE_PREFIX + upload.key,\n JSON.stringify(upload),\n );\n } catch {\n // localStorage unavailable (SSR, quota exceeded) — silently skip.\n }\n },\n\n delete(key) {\n try {\n localStorage.removeItem(STORAGE_PREFIX + key);\n } catch {\n // ignore\n }\n },\n };\n}\n","import type { StoredUpload, UploadStore } from \"../types/upload-store\";\n\n/**\n * In-memory `UploadStore` — safe for SSR and server-component environments.\n *\n * State is cleared on page reload. Useful as a fallback, for testing, or\n * when you want session-scoped resume without touching `localStorage`.\n *\n * @example\n * ```ts\n * const store = createMemoryStore();\n * useUpload({ api, uploadStore: store });\n * ```\n */\nexport function createMemoryStore(): UploadStore {\n const map = new Map<string, StoredUpload>();\n\n return {\n get(key, fileSize) {\n const stored = map.get(key);\n if (!stored) return null;\n return stored.fileSize === fileSize ? stored : null;\n },\n\n set(upload) {\n map.set(upload.key, upload);\n },\n\n delete(key) {\n map.delete(key);\n },\n };\n}\n","export const DEFAULT_MULTIPART_THRESHOLD = 50 * 1024 * 1024; // 50 MB\nexport const DEFAULT_PART_SIZE = 5 * 1024 * 1024; // 5 MB\nexport const MAX_RETRIES = 3;\nexport const RETRY_BASE_DELAY = 1_000; // ms\nexport const DEFAULT_CONCURRENT_PARTS = 2;\nexport const DEFAULT_CONCURRENT_FILES = 2;\n","import { MAX_RETRIES, RETRY_BASE_DELAY } from \"./constants\";\nimport type { RetryConfig } from \"../types\";\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n retryConfig: RetryConfig | undefined,\n signal?: AbortSignal,\n): Promise<T> {\n const maxRetries = retryConfig?.maxRetries ?? MAX_RETRIES;\n const baseDelay = retryConfig?.baseDelay ?? RETRY_BASE_DELAY;\n\n let lastError: unknown;\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if ((err as Error).name === \"AbortError\") throw err;\n lastError = err;\n if (attempt < maxRetries) {\n const delay = baseDelay * 2 ** attempt;\n await new Promise((r) => setTimeout(r, delay));\n if (signal?.aborted)\n throw new DOMException(\"Upload aborted\", \"AbortError\");\n }\n }\n }\n throw lastError;\n}\n","import type { UploadProgress } from \"../types\";\n\n/**\n * Uploads a file directly to S3 using a presigned POST form.\n *\n * All policy fields (acl, Content-Type, content-length-range, signature, etc.)\n * are embedded in `fields` and must be appended to the FormData **before** the\n * file — this is an S3 requirement. The size constraint is enforced by S3 at\n * the storage layer, so the server never needs to re-validate it.\n */\nexport function uploadSimple(\n file: File,\n url: string,\n fields: Record<string, string>,\n onProgress?: (progress: UploadProgress) => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n const onAbort = () => {\n xhr.abort();\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n xhr.upload.addEventListener(\"progress\", (e) => {\n if (e.lengthComputable) {\n onProgress?.({\n loaded: e.loaded,\n total: e.total,\n percent: Math.round((e.loaded / e.total) * 100),\n });\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (xhr.status >= 200 && xhr.status < 300) {\n onProgress?.({ loaded: file.size, total: file.size, percent: 100 });\n resolve();\n } else {\n reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"Upload failed: network error\"));\n });\n\n xhr.addEventListener(\"abort\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n });\n\n // S3 presigned POST: policy fields must come before the file field.\n const formData = new FormData();\n for (const [k, v] of Object.entries(fields)) {\n formData.append(k, v);\n }\n formData.append(\"file\", file);\n\n xhr.open(\"POST\", url);\n xhr.send(formData);\n });\n}\n\n/**\n * Uploads a file directly to S3 using a presigned PUT URL.\n *\n * Use this when the server is configured with `upload.method = \"put\"` — for\n * example with Cloudflare R2 which does not support presigned POST.\n * The `headers` object must match exactly what was signed on the server\n * (Content-Type, Content-Disposition, x-amz-meta-*, etc.).\n */\nexport function uploadPut(\n file: File,\n url: string,\n headers: Record<string, string>,\n onProgress?: (progress: UploadProgress) => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n const onAbort = () => {\n xhr.abort();\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n xhr.upload.addEventListener(\"progress\", (e) => {\n if (e.lengthComputable) {\n onProgress?.({\n loaded: e.loaded,\n total: e.total,\n percent: Math.round((e.loaded / e.total) * 100),\n });\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (xhr.status >= 200 && xhr.status < 300) {\n onProgress?.({ loaded: file.size, total: file.size, percent: 100 });\n resolve();\n } else {\n reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"Upload failed: network error\"));\n });\n\n xhr.addEventListener(\"abort\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n });\n\n xhr.open(\"PUT\", url);\n for (const [k, v] of Object.entries(headers)) {\n xhr.setRequestHeader(k, v);\n }\n xhr.send(file);\n });\n}\n","export function uploadPart(\n blob: Blob,\n presignedUrl: string,\n partLoaded: { bytes: number },\n totalSize: number,\n reportProgress: () => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n const onAbort = () => {\n xhr.abort();\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n xhr.upload.addEventListener(\"progress\", (e) => {\n if (e.lengthComputable) {\n partLoaded.bytes = e.loaded;\n reportProgress();\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (xhr.status >= 200 && xhr.status < 300) {\n partLoaded.bytes = blob.size;\n reportProgress();\n resolve();\n } else {\n reject(new Error(`Part upload failed: ${xhr.status}`));\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"Part upload failed: network error\"));\n });\n\n xhr.addEventListener(\"abort\", () => {\n signal?.removeEventListener(\"abort\", onAbort);\n reject(new DOMException(\"Upload aborted\", \"AbortError\"));\n });\n\n xhr.open(\"PUT\", presignedUrl);\n xhr.send(blob);\n });\n}\n","import type {\n UploadProgress,\n UploadRequestOptions,\n RetryConfig,\n} from \"../types\";\nimport type { S3Api } from \"../types/s3-api\";\nimport type { UploadStore } from \"../types/upload-store\";\nimport { withRetry } from \"./retry\";\nimport { uploadPart } from \"./part\";\n\n/** Returns the byte size of a specific part (last part may be smaller). */\nfunction resolvePartSize(\n partIndex: number,\n totalParts: number,\n partSize: number,\n fileSize: number,\n): number {\n return partIndex === totalParts - 1\n ? fileSize - partIndex * partSize\n : partSize;\n}\n\nexport async function uploadMultipart(\n api: S3Api,\n file: File,\n objectKey: string,\n partSize: number,\n concurrentParts: number,\n onProgress?: (progress: UploadProgress) => void,\n signal?: AbortSignal,\n requestOptions?: UploadRequestOptions,\n retryConfig?: RetryConfig,\n uploadStore?: UploadStore | false,\n onPartUpload?: (partNumber: number, totalParts: number) => void,\n onMultipartInit?: (uploadId: string, key: string) => void,\n): Promise<string | undefined> {\n const bucket = requestOptions?.bucket;\n const contentType = requestOptions?.contentType ?? file.type;\n\n // Resolve the active store.\n // null → resumability disabled (uploadStore omitted, false, or SSR)\n // store → resumability enabled; persist uploadId across sessions\n const store: UploadStore | null =\n uploadStore != null && uploadStore !== false ? uploadStore : null;\n\n let uploadId: string;\n let key: string;\n const completedPartNumbers = new Set<number>();\n\n // ── Attempt to resume an existing upload ─────────────────────────────────\n const existing = store ? await store.get(objectKey, file.size) : null;\n\n if (existing) {\n try {\n // Verify the uploadId is still valid on S3 and fetch already-done parts.\n const { parts } = await api.multipart.listParts({\n key: existing.key,\n uploadId: existing.uploadId,\n bucket: bucket ?? existing.bucket,\n });\n uploadId = existing.uploadId;\n key = existing.key;\n for (const p of parts) completedPartNumbers.add(p.partNumber);\n onMultipartInit?.(uploadId, key);\n } catch {\n // uploadId is expired or no longer valid — start a fresh upload.\n await store?.delete(objectKey);\n const result = await api.multipart.init({\n key: objectKey,\n contentType,\n fileSize: file.size,\n fileName:\n requestOptions?.fileName !== null\n ? (requestOptions?.fileName ?? file.name)\n : undefined,\n metadata: requestOptions?.metadata,\n bucket,\n acl: requestOptions?.acl,\n });\n uploadId = result.uploadId;\n key = result.key;\n await store?.set({ uploadId, key, fileSize: file.size, bucket });\n onMultipartInit?.(uploadId, key);\n }\n } else {\n const result = await api.multipart.init({\n key: objectKey,\n contentType,\n fileSize: file.size,\n fileName:\n requestOptions?.fileName !== null\n ? (requestOptions?.fileName ?? file.name)\n : undefined,\n metadata: requestOptions?.metadata,\n bucket,\n acl: requestOptions?.acl,\n });\n uploadId = result.uploadId;\n key = result.key;\n await store?.set({ uploadId, key, fileSize: file.size, bucket });\n onMultipartInit?.(uploadId, key);\n }\n\n // ── Setup progress tracking ───────────────────────────────────────────────\n const totalParts = Math.ceil(file.size / partSize);\n\n // Pre-fill progress bytes for already-completed parts.\n const partProgress: Array<{ bytes: number }> = Array.from(\n { length: totalParts },\n (_, i) => ({\n bytes: completedPartNumbers.has(i + 1)\n ? resolvePartSize(i, totalParts, partSize, file.size)\n : 0,\n }),\n );\n\n // Pre-register completed parts so complete() receives a full list.\n const parts: Array<{ partNumber: number }> = Array.from(\n completedPartNumbers,\n (n) => ({ partNumber: n }),\n );\n\n const reportProgress = () => {\n const loaded = partProgress.reduce((sum, p) => sum + p.bytes, 0);\n onProgress?.({\n loaded,\n total: file.size,\n percent: Math.round((loaded / file.size) * 100),\n });\n };\n\n // Report initial progress for pre-completed parts before uploading starts.\n if (completedPartNumbers.size > 0) {\n reportProgress();\n }\n\n // ── Upload remaining parts ────────────────────────────────────────────────\n try {\n for (\n let batchStart = 0;\n batchStart < totalParts;\n batchStart += concurrentParts\n ) {\n if (signal?.aborted) {\n throw new DOMException(\"Upload aborted\", \"AbortError\");\n }\n\n const batchEnd = Math.min(batchStart + concurrentParts, totalParts);\n const batch: Array<Promise<{ partNumber: number }>> = [];\n\n for (let i = batchStart; i < batchEnd; i++) {\n const partNumber = i + 1;\n\n // Skip parts that were already uploaded in a previous attempt.\n if (completedPartNumbers.has(partNumber)) continue;\n\n const start = i * partSize;\n const end = Math.min(start + partSize, file.size);\n const blob = file.slice(start, end);\n\n batch.push(\n withRetry(\n async () => {\n const { presignedUrl } = await api.multipart.signPart({\n key,\n uploadId,\n partNumber,\n partSize: blob.size,\n bucket,\n });\n\n partProgress[i].bytes = 0;\n\n await uploadPart(\n blob,\n presignedUrl,\n partProgress[i],\n file.size,\n reportProgress,\n signal,\n );\n\n onPartUpload?.(partNumber, totalParts);\n return { partNumber };\n },\n retryConfig,\n signal,\n ),\n );\n }\n\n const batchResults = await Promise.all(batch);\n parts.push(...batchResults);\n }\n\n parts.sort((a, b) => a.partNumber - b.partNumber);\n\n const result = await api.multipart.complete({\n key,\n uploadId,\n parts,\n bucket,\n });\n\n // Upload finished successfully — remove from store.\n await store?.delete(objectKey);\n\n onProgress?.({ loaded: file.size, total: file.size, percent: 100 });\n return result.eTag;\n } catch (err) {\n if (store === null) {\n // Resumability is disabled — clean up the S3 multipart upload immediately.\n api.multipart.abort({ key, uploadId, bucket }).catch(() => {});\n }\n // With store active: preserve uploadId so the upload can be resumed later.\n // The S3 multipart upload is left open (expires automatically per bucket policy).\n throw err;\n }\n}\n","import type {\n UploadConfig,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n} from \"../types\";\nimport type { S3Api } from \"../types/s3-api\";\nimport {\n DEFAULT_MULTIPART_THRESHOLD,\n DEFAULT_CONCURRENT_PARTS,\n DEFAULT_PART_SIZE,\n} from \"./constants\";\nimport { withRetry } from \"./retry\";\nimport { uploadSimple, uploadPut } from \"./simple\";\nimport { uploadMultipart } from \"./multipart\";\n\nexport type UploadEngineCallbacks = {\n onProgress?: (progress: UploadProgress) => void;\n /** Called when the upload transitions between internal phases. */\n onPhaseChange?: (phase: \"presigning\" | \"uploading\" | \"finalizing\") => void;\n /** Called after each individual multipart part is successfully uploaded. */\n onPartUpload?: (partNumber: number, totalParts: number) => void;\n /** Called once after `CreateMultipartUpload` succeeds with the S3-assigned `uploadId` and final object `key`. */\n onMultipartInit?: (uploadId: string, key: string) => void;\n};\n\nexport async function uploadFile(\n api: S3Api,\n file: File,\n objectKey: string,\n config: UploadConfig = {},\n callbacks: UploadEngineCallbacks = {},\n signal?: AbortSignal,\n requestOptions?: UploadRequestOptions,\n): Promise<UploadResult> {\n const threshold = config.multipartThreshold ?? DEFAULT_MULTIPART_THRESHOLD;\n const useMultipart = config.multipart === true && file.size >= threshold;\n const concurrentParts = config.concurrentParts ?? DEFAULT_CONCURRENT_PARTS;\n const partSize =\n requestOptions?.partSize ?? config.partSize ?? DEFAULT_PART_SIZE;\n const contentType = requestOptions?.contentType ?? file.type;\n\n let eTag: string | undefined;\n\n if (useMultipart) {\n callbacks.onPhaseChange?.(\"uploading\");\n eTag = await uploadMultipart(\n api,\n file,\n objectKey,\n partSize,\n concurrentParts,\n callbacks.onProgress,\n signal,\n requestOptions,\n config.retry,\n config.uploadStore,\n callbacks.onPartUpload,\n callbacks.onMultipartInit,\n );\n } else {\n await withRetry(\n async () => {\n callbacks.onPhaseChange?.(\"presigning\");\n const presign = await api.upload({\n key: objectKey,\n contentType,\n fileSize: file.size,\n fileName:\n requestOptions?.fileName !== null\n ? (requestOptions?.fileName ?? file.name)\n : undefined,\n metadata: requestOptions?.metadata,\n bucket: requestOptions?.bucket,\n acl: requestOptions?.acl,\n });\n callbacks.onPhaseChange?.(\"uploading\");\n if (presign.method === \"put\") {\n await uploadPut(\n file,\n presign.url,\n presign.headers ?? {},\n callbacks.onProgress,\n signal,\n );\n } else {\n await uploadSimple(\n file,\n presign.url,\n presign.fields ?? {},\n callbacks.onProgress,\n signal,\n );\n }\n },\n config.retry,\n signal,\n );\n\n callbacks.onPhaseChange?.(\"finalizing\");\n const confirmed = await api.confirm({\n key: objectKey,\n bucket: requestOptions?.bucket,\n });\n eTag = confirmed.eTag;\n }\n\n return { key: objectKey, eTag };\n}\n","import type {\n UploadConfig,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n} from \"../types\";\nimport type { S3Api } from \"../types/s3-api\";\nimport { DEFAULT_CONCURRENT_FILES } from \"./constants\";\nimport { uploadFile } from \"./upload-file\";\n\nexport type FileItemStatus = \"pending\" | \"uploading\" | \"success\" | \"error\";\n\nexport type FileItem = {\n id: string;\n file: File;\n objectKey: string;\n status: FileItemStatus;\n progress: UploadProgress;\n result: UploadResult | null;\n error: string | null;\n};\n\nexport type MultiUploadCallbacks = {\n onFileProgress?: (id: string, progress: UploadProgress) => void;\n onFileSuccess?: (id: string, result: UploadResult) => void;\n onFileError?: (id: string, error: string) => void;\n onTotalProgress?: (progress: UploadProgress) => void;\n};\n\nexport async function uploadFiles(\n api: S3Api,\n items: Array<{ id: string; file: File; objectKey: string }>,\n config: UploadConfig = {},\n callbacks: MultiUploadCallbacks = {},\n signal?: AbortSignal,\n getRequestOptions?: (file: File) => UploadRequestOptions,\n): Promise<FileItem[]> {\n const results: FileItem[] = items.map((item) => ({\n ...item,\n status: \"pending\" as FileItemStatus,\n progress: { loaded: 0, total: item.file.size, percent: 0 },\n result: null,\n error: null,\n }));\n\n const reportTotalProgress = () => {\n const loaded = results.reduce((sum, r) => sum + r.progress.loaded, 0);\n const total = results.reduce((sum, r) => sum + r.progress.total, 0);\n callbacks.onTotalProgress?.({\n loaded,\n total,\n percent: total > 0 ? Math.round((loaded / total) * 100) : 0,\n });\n };\n\n let nextIndex = 0;\n\n const processNext = async (): Promise<void> => {\n while (nextIndex < results.length) {\n if (signal?.aborted) return;\n const idx = nextIndex++;\n const item = results[idx];\n\n item.status = \"uploading\";\n\n try {\n const result = await uploadFile(\n api,\n item.file,\n item.objectKey,\n config,\n {\n onProgress: (progress) => {\n item.progress = progress;\n callbacks.onFileProgress?.(item.id, progress);\n reportTotalProgress();\n },\n },\n signal,\n getRequestOptions?.(item.file),\n );\n item.status = \"success\";\n item.result = result;\n item.progress = {\n loaded: item.file.size,\n total: item.file.size,\n percent: 100,\n };\n callbacks.onFileSuccess?.(item.id, result);\n reportTotalProgress();\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n item.status = \"error\";\n item.error = \"Upload cancelled\";\n return;\n }\n const message = err instanceof Error ? err.message : \"Upload failed\";\n item.status = \"error\";\n item.error = message;\n callbacks.onFileError?.(item.id, message);\n reportTotalProgress();\n }\n }\n };\n\n const concurrentFiles = config.concurrentFiles ?? DEFAULT_CONCURRENT_FILES;\n const workers = Array.from(\n { length: Math.min(concurrentFiles, items.length) },\n () => processNext(),\n );\n await Promise.all(workers);\n\n return results;\n}\n","/**\n * Formats a byte count into a human-readable string.\n *\n * @example\n * ```ts\n * formatFileSize(0) // \"0 B\"\n * formatFileSize(1500) // \"1.5 KB\"\n * formatFileSize(1048576) // \"1.0 MB\"\n * ```\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 B\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const size = bytes / Math.pow(1024, i);\n return `${size.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;\n}\n","/**\n * Validates a `File` against accept-list and size constraints.\n *\n * Returns a human-readable error string when validation fails,\n * or `null` when the file is valid.\n *\n * Mirrors the server-side `validateFile` so you can apply the same\n * rules on the client before initiating an upload.\n *\n * @example\n * ```ts\n * const error = validateFile(file, {\n * accept: [\"image/*\", \".pdf\"],\n * maxFileSize: 10 * 1024 * 1024, // 10 MB\n * });\n * if (error) toast.error(error);\n * ```\n */\nexport function validateFile(\n file: File,\n options: { accept?: string[]; maxFileSize?: number },\n): string | null {\n if (options.accept?.length) {\n const allowed = options.accept.some((type) => {\n if (type.startsWith(\".\")) {\n return file.name.toLowerCase().endsWith(type.toLowerCase());\n }\n if (type.endsWith(\"/*\")) {\n return file.type.startsWith(type.replace(\"/*\", \"/\"));\n }\n return file.type === type;\n });\n if (!allowed) {\n const ext = file.name.includes(\".\") ? file.name.split(\".\").pop() : null;\n return `File type \"${ext ? `.${ext}` : file.type || \"unknown\"}\" is not allowed`;\n }\n }\n\n if (file.size === 0) {\n return \"File is empty\";\n }\n\n if (options.maxFileSize && file.size > options.maxFileSize) {\n const maxMB = (options.maxFileSize / (1024 * 1024)).toFixed(1);\n return `File size exceeds ${maxMB} MB limit`;\n }\n\n return null;\n}\n","/**\n * Extracts a display filename from a `Content-Disposition` response header.\n *\n * Prefers the RFC 5987 `filename*=UTF-8''…` encoding (full Unicode support)\n * over the plain ASCII `filename=\"…\"` fallback.\n *\n * @param header The raw `Content-Disposition` header value (or `null`).\n * @param fallback Returned when no filename can be extracted.\n *\n * @example\n * ```ts\n * const name = parseContentDispositionFilename(\n * response.headers.get(\"content-disposition\"),\n * \"download\",\n * );\n * ```\n */\nexport function parseContentDispositionFilename(\n header: string | null,\n fallback: string,\n): string {\n if (!header) return fallback;\n const starMatch = header.match(/filename\\*=UTF-8''([^;,\\s]+)/i);\n if (starMatch) {\n try {\n return decodeURIComponent(starMatch[1]);\n } catch {\n // fall through to ASCII fallback\n }\n }\n const match = header.match(/filename=\"([^\"]+)\"/i);\n if (match) return match[1];\n return fallback;\n}\n","import { formatFileSize } from \"./format-file-size\";\n\n/**\n * Formats upload progress as a human-readable transfer string.\n *\n * @param loaded Bytes transferred so far.\n * @param total Total bytes to transfer (0 means unknown).\n * @param percent Transfer percentage (0–100).\n *\n * @example\n * ```ts\n * formatUploadProgress(1_200_000, 5_600_000, 21)\n * // → \"1.2 MB / 5.6 MB (21%)\"\n *\n * formatUploadProgress(1_200_000, 0, 0)\n * // → \"1.2 MB\"\n * ```\n */\nexport function formatUploadProgress(\n loaded: number,\n total: number,\n percent: number,\n): string {\n const loadedStr = formatFileSize(loaded);\n if (!total) return loadedStr;\n return `${loadedStr} / ${formatFileSize(total)} (${Math.round(percent)}%)`;\n}\n","import { formatFileSize } from \"./format-file-size\";\n\n/**\n * Formats a transfer speed (bytes/second) as a human-readable string.\n *\n * @example\n * formatSpeed(1_200_000) // → \"1.2 MB/s\"\n * formatSpeed(512) // → \"512 B/s\"\n */\nexport function formatSpeed(bytesPerSecond: number): string {\n return `${formatFileSize(bytesPerSecond)}/s`;\n}\n","/**\n * Formats an estimated remaining time given the remaining bytes and current speed.\n *\n * Returns `null` when speed is 0 or nothing remains (not yet calculable).\n *\n * @example\n * formatEta(4_400_000, 450_000) // → \"9s\"\n * formatEta(4_400_000, 75_000) // → \"58s\"\n * formatEta(90_000_000, 1_500_000) // → \"1m\"\n * formatEta(5_400_000_000, 500_000) // → \"3h\"\n */\nexport function formatEta(\n remainingBytes: number,\n bytesPerSecond: number,\n): string | null {\n if (bytesPerSecond <= 0 || remainingBytes <= 0) return null;\n const totalSeconds = remainingBytes / bytesPerSecond;\n\n if (totalSeconds < 60) return `${Math.ceil(totalSeconds)}s`;\n\n const totalMinutes = totalSeconds / 60;\n if (totalMinutes < 60) return `${Math.ceil(totalMinutes)}m`;\n\n const hours = Math.floor(totalMinutes / 60);\n const mins = Math.ceil(totalMinutes % 60);\n return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;\n}\n","/**\n * Builds an S3 object key by joining path segments with `/`.\n *\n * Trims leading/trailing slashes from each segment and removes empty ones,\n * so you can safely pass optional parts without worrying about double-slashes.\n *\n * Follows the recommended better-s3 key convention:\n * - Personal mode: `buildObjectKey(userId, `${nanoid()}.${ext}`)` → `\"user_123/abc.png\"`\n * - Org mode: `buildObjectKey(orgId, userId, `${nanoid()}.${ext}`)` → `\"org_1/user_123/abc.png\"`\n *\n * @example\n * ```ts\n * buildObjectKey(\"user_123\", \"uploads\", \"photo.png\")\n * // → \"user_123/uploads/photo.png\"\n *\n * buildObjectKey(\"org_1\", \"\", \"user_123\", \"doc.pdf\")\n * // → \"org_1/user_123/doc.pdf\"\n * ```\n */\nexport function buildObjectKey(...parts: string[]): string {\n return parts\n .map((p) => p.replace(/^\\/+|\\/+$/g, \"\"))\n .filter(Boolean)\n .join(\"/\");\n}\n","/**\n * Extracts the lowercase file extension (without the dot) from a filename.\n *\n * Returns an empty string when the filename has no extension.\n *\n * @example\n * ```ts\n * getFileExtension(\"photo.JPG\") // \"jpg\"\n * getFileExtension(\"archive.tar.gz\") // \"gz\"\n * getFileExtension(\"README\") // \"\"\n * ```\n */\nexport function getFileExtension(filename: string): string {\n const dotIndex = filename.lastIndexOf(\".\");\n if (dotIndex < 1) return \"\";\n return filename.slice(dotIndex + 1).toLowerCase();\n}\n","/**\n * Truncates a filename while always preserving the file extension.\n * The cut happens before the extension so the extension is always visible.\n *\n * truncateFilename(\"namenamenamenamename.pdf\", 20) → \"namenamename… .pdf\"\n * truncateFilename(\"short.pdf\", 20) → \"short.pdf\"\n * truncateFilename(\".gitignore\", 8) → \".gitigno…\"\n */\nexport function truncateFilename(name: string, maxChars = 26): string {\n if (name.length <= maxChars) return name;\n const dotIndex = name.lastIndexOf(\".\");\n // No extension, or name begins with a dot (hidden file)\n if (dotIndex <= 0) {\n return name.slice(0, maxChars - 1) + \"…\";\n }\n const ext = name.slice(dotIndex); // e.g. \".pdf\"\n const available = maxChars - ext.length - 1; // chars of base before \"…\"\n if (available <= 0) {\n // Extension alone is very long — fall back to plain tail truncation\n return name.slice(0, maxChars - 1) + \"…\";\n }\n return name.slice(0, available) + \"… \" + ext;\n}\n","/**\n * Creates a sliding-window transfer speed calculator.\n *\n * Tracks bytes transferred over a rolling time window to produce a smooth,\n * instantaneous speed reading in bytes/second.\n *\n * @param windowMs Rolling window duration in milliseconds. @default 3000\n */\nexport function createSpeedTracker(windowMs = 3000) {\n const samples: Array<{ t: number; loaded: number }> = [];\n\n return {\n /**\n * Record the latest cumulative `loaded` byte count.\n * Returns the current speed in bytes/second (0 until at least 2 samples exist).\n */\n update(loaded: number): number {\n const now = Date.now();\n samples.push({ t: now, loaded });\n\n // Prune samples older than the window, but keep at least one anchor.\n const cutoff = now - windowMs;\n while (samples.length > 1 && samples[0].t < cutoff) {\n samples.shift();\n }\n\n if (samples.length < 2) return 0;\n\n const oldest = samples[0];\n const newest = samples[samples.length - 1];\n const deltaMs = newest.t - oldest.t;\n const deltaBytes = newest.loaded - oldest.loaded;\n\n return deltaMs > 0 ? Math.round((deltaBytes / deltaMs) * 1000) : 0;\n },\n\n reset() {\n samples.length = 0;\n },\n };\n}\n\nexport type SpeedTracker = ReturnType<typeof createSpeedTracker>;\n","import { useRef } from \"react\";\n\n/**\n * Keeps a ref in sync with the latest value on every render.\n *\n * Use inside `useCallback(fn, [])` to read the latest prop / option value\n * without making the callback depend on it (stale-closure-free stable refs).\n *\n * @internal — not part of the public API.\n */\nexport function useLiveRef<T>(value: T) {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n}\n","\"use client\";\n\nimport { useCallback, useContext, useRef, useState } from \"react\";\nimport type { S3Api } from \"../types/s3-api\";\nimport { S3Context } from \"../s3-provider\";\nimport { validateFile } from \"../helpers\";\nimport { createSpeedTracker } from \"../helpers/speed-tracker\";\nimport { useLiveRef } from \"../internal-helpers\";\nimport type {\n UploadConfig,\n UploadHooks,\n UploadPhase,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n} from \"../types\";\nimport { uploadFile } from \"../upload\";\n\nexport type UseUploadOptions = UploadConfig &\n UploadHooks & {\n /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */\n api?: S3Api;\n };\n\nexport type UseUploadState = {\n phase: UploadPhase;\n progress: UploadProgress;\n error: string | null;\n result: UploadResult | null;\n fileName: string | null;\n fileSize: number | null;\n};\n\nexport type UseUploadReturn = UseUploadState & {\n /**\n * Start an upload.\n *\n * Safe to call again after `success`, `error`, or `cancel` — state is reset\n * automatically before the new upload begins.\n *\n * If `uploadStore` is configured and a previous upload for the same\n * `objectKey` was interrupted (e.g. via `detach()`), the engine will find\n * the stored `uploadId`, call `listParts`, and resume from the last completed\n * part rather than starting a new multipart upload.\n */\n upload: (\n file: File,\n objectKey: string,\n requestOptions?: UploadRequestOptions,\n ) => Promise<void>;\n /**\n * Abort the upload and fully clean up all resources.\n *\n * - Stops the in-flight network request immediately.\n * - For multipart uploads: calls `AbortMultipartUpload` on S3 so incomplete\n * parts are freed right away (instead of waiting for the bucket lifecycle\n * policy to expire them).\n * - Removes the `uploadStore` entry if one was provided.\n * - Resets state to `idle`.\n *\n * Use this for a \"Cancel\" button that the user explicitly clicks to abandon\n * the upload entirely.\n */\n cancel: () => void;\n /**\n * Stop the upload and — when multipart with `uploadStore` is active —\n * preserve S3 parts and the store entry for a future resume.\n *\n * Compared to `cancel()`:\n * - Does **not** call `AbortMultipartUpload` (parts stay on S3).\n * - Does **not** remove the `uploadStore` entry.\n * - Does **not** fire the `onCancel` callback.\n *\n * The next call to `upload(sameFile, sameKey)` will detect the stored\n * `uploadId`, verify the existing parts via `listParts`, and continue\n * uploading from where it stopped.\n *\n * For **simple uploads** or multipart **without** `uploadStore`, this is\n * identical to `cancel()` — there is no S3 state worth preserving.\n *\n * Intended for custom UIs that want to offer a \"save for later / resume\"\n * workflow. The built-in UI components always use `cancel()`.\n */\n detach: () => void;\n /**\n * Reset UI state to `idle` without touching any S3 or store resources.\n *\n * - Stops the in-flight network request if one is active.\n * - Does **not** call `AbortMultipartUpload`.\n * - Does **not** modify `uploadStore`.\n * - Does **not** fire `onCancel`.\n *\n * Use this to clear an error or success state from the UI, or when you\n * handle cleanup yourself outside this hook.\n */\n reset: () => void;\n};\n\nconst INITIAL_PROGRESS: UploadProgress = { loaded: 0, total: 0, percent: 0 };\n\nconst INITIAL_STATE: UseUploadState = {\n phase: \"idle\",\n progress: INITIAL_PROGRESS,\n error: null,\n result: null,\n fileName: null,\n fileSize: null,\n};\n\ntype ActiveUpload = {\n file: File;\n objectKey: string;\n /** S3 key as returned by the server (may differ from objectKey). */\n serverKey: string;\n uploadId?: string;\n bucket?: string;\n requestOptions?: UploadRequestOptions;\n};\n\nexport function useUpload(options: UseUploadOptions): UseUploadReturn {\n const [state, setState] = useState<UseUploadState>(INITIAL_STATE);\n const contextApi = useContext(S3Context);\n const optsRef = useLiveRef(options);\n const apiRef = useLiveRef(contextApi);\n const abortRef = useRef<AbortController | null>(null);\n /** Tracks the in-flight upload so cancel/detach can access uploadId and key. */\n const activeUploadRef = useRef<ActiveUpload | null>(null);\n /** Set before aborting so the AbortError catch skips cancel callbacks. */\n const detachingRef = useRef(false);\n const speedTrackerRef = useRef(createSpeedTracker());\n const lastSpeedRef = useRef<number | undefined>(undefined);\n const lastSpeedUpdateRef = useRef(0);\n\n const upload = useCallback(\n async (\n file: File,\n objectKey: string,\n requestOptions?: UploadRequestOptions,\n ) => {\n setState({\n ...INITIAL_STATE,\n phase: \"validating\",\n fileName: file.name,\n fileSize: file.size,\n });\n\n const opts = optsRef.current;\n const api = opts.api ?? apiRef.current;\n if (!api)\n throw new Error(\n \"[better-s3] No S3Api client found. Pass `api` to useUpload or wrap with <S3Provider>.\",\n );\n\n const validationError = validateFile(file, {\n accept: opts.accept,\n maxFileSize: opts.maxFileSize,\n });\n if (validationError) {\n setState((s) => ({ ...s, phase: \"error\", error: validationError }));\n opts.onError?.(file, new Error(validationError), \"validating\");\n return;\n }\n\n if (opts.beforeUpload) {\n const allowed = await opts.beforeUpload(file);\n if (!allowed) {\n setState((s) => ({\n ...s,\n phase: \"error\",\n error: \"Upload blocked by beforeUpload hook\",\n }));\n opts.onError?.(file, new Error(\"blocked\"), \"validating\");\n return;\n }\n }\n\n speedTrackerRef.current.reset();\n lastSpeedRef.current = undefined;\n lastSpeedUpdateRef.current = 0;\n setState((s) => ({ ...s, phase: \"presigning\" }));\n opts.onUploadStart?.(file, objectKey);\n\n const controller = new AbortController();\n abortRef.current = controller;\n activeUploadRef.current = {\n file,\n objectKey,\n serverKey: objectKey,\n bucket: requestOptions?.bucket,\n requestOptions,\n };\n\n try {\n const result = await uploadFile(\n api,\n file,\n objectKey,\n {\n multipart: opts.multipart,\n multipartThreshold: opts.multipartThreshold,\n concurrentParts: opts.concurrentParts,\n partSize: opts.partSize,\n retry: opts.retry,\n uploadStore: opts.uploadStore,\n },\n {\n onProgress: (progress) => {\n const rawSpeed = speedTrackerRef.current.update(progress.loaded);\n const now = Date.now();\n if (rawSpeed > 0 && now - lastSpeedUpdateRef.current >= 500) {\n lastSpeedRef.current = rawSpeed;\n lastSpeedUpdateRef.current = now;\n }\n const speed = lastSpeedRef.current;\n const p = speed ? { ...progress, speed } : progress;\n setState((s) => ({ ...s, progress: p }));\n opts.onProgress?.(file, p);\n },\n onPhaseChange: (phase) => setState((s) => ({ ...s, phase })),\n onPartUpload: (partNumber, totalParts) =>\n opts.onPartUpload?.(file, partNumber, totalParts),\n onMultipartInit: (uploadId, serverKey) => {\n if (activeUploadRef.current) {\n activeUploadRef.current.uploadId = uploadId;\n activeUploadRef.current.serverKey = serverKey;\n }\n opts.onMultipartInit?.(file, uploadId);\n },\n },\n controller.signal,\n requestOptions,\n );\n\n setState((s) => ({\n ...s,\n phase: \"success\",\n result,\n progress: { loaded: file.size, total: file.size, percent: 100 },\n }));\n await opts.onSuccess?.(file, result);\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n if (detachingRef.current) {\n detachingRef.current = false;\n return;\n }\n opts.onCancel?.(file);\n setState(INITIAL_STATE);\n return;\n }\n const message = err instanceof Error ? err.message : \"Upload failed\";\n setState((s) => ({ ...s, phase: \"error\", error: message }));\n opts.onError?.(file, err, \"uploading\");\n } finally {\n abortRef.current = null;\n activeUploadRef.current = null;\n }\n },\n [],\n );\n\n const cancel = useCallback(() => {\n const opts = optsRef.current;\n const api = opts.api ?? apiRef.current;\n const active = activeUploadRef.current;\n abortRef.current?.abort();\n if (active && api) {\n const { objectKey, serverKey, uploadId, bucket } = active;\n const store = opts.uploadStore;\n if (store != null && store !== false) {\n void Promise.resolve(store.delete(objectKey)).catch(() => {});\n }\n if (uploadId) {\n api.multipart\n .abort({ key: serverKey, uploadId, bucket })\n .catch(() => {});\n }\n }\n setState(INITIAL_STATE);\n }, []);\n\n const detach = useCallback(() => {\n const active = activeUploadRef.current;\n if (!active) return;\n // Signal the AbortError catch not to fire onCancel or re-reset state.\n detachingRef.current = true;\n abortRef.current?.abort();\n // multipart.ts already preserves the store entry when store != null,\n // so no extra cleanup is needed here for the resumable path.\n // For simple uploads or multipart without store the abort triggers\n // AbortMultipartUpload automatically inside multipart.ts.\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n return { ...state, upload, cancel, detach, reset };\n}\n","\"use client\";\n\nimport { useCallback, useContext, useRef, useState } from \"react\";\nimport type { S3Api } from \"../types/s3-api\";\nimport { S3Context } from \"../s3-provider\";\nimport { validateFile } from \"../helpers\";\nimport { createSpeedTracker } from \"../helpers/speed-tracker\";\nimport { useLiveRef } from \"../internal-helpers\";\nimport type {\n UploadConfig,\n UploadProgress,\n UploadResult,\n UploadRequestOptions,\n MultiUploadPhase,\n MultiUploadFileState,\n MultiUploadHooks,\n} from \"../types\";\nimport { uploadFiles } from \"../upload\";\n\nexport type UseMultiUploadOptions = UploadConfig &\n MultiUploadHooks & {\n /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */\n api?: S3Api;\n /** Static request options applied to all files */\n uploadOptions?: UploadRequestOptions;\n /** Per-file request options (overrides uploadOptions) */\n getUploadOptions?: (file: File) => UploadRequestOptions;\n };\n\nexport type UseMultiUploadState = {\n phase: MultiUploadPhase;\n files: MultiUploadFileState[];\n totalProgress: UploadProgress;\n error: string | null;\n};\n\nexport type UseMultiUploadReturn = UseMultiUploadState & {\n upload: (files: File[], resolveKey: (file: File) => string) => Promise<void>;\n cancel: () => void;\n reset: () => void;\n};\n\nconst INITIAL_PROGRESS: UploadProgress = { loaded: 0, total: 0, percent: 0 };\n\nconst INITIAL_STATE: UseMultiUploadState = {\n phase: \"idle\",\n files: [],\n totalProgress: INITIAL_PROGRESS,\n error: null,\n};\n\nfunction generateId() {\n return crypto.randomUUID();\n}\n\nexport function useMultiUpload(\n options: UseMultiUploadOptions,\n): UseMultiUploadReturn {\n const [state, setState] = useState<UseMultiUploadState>(INITIAL_STATE);\n const contextApi = useContext(S3Context);\n const optsRef = useLiveRef(options);\n const apiRef = useLiveRef(contextApi);\n const abortRef = useRef<AbortController | null>(null);\n const resettingRef = useRef(false);\n const fileMapRef = useRef<Map<string, File>>(new Map());\n const fileSpeedTrackersRef = useRef<\n Map<string, ReturnType<typeof createSpeedTracker>>\n >(new Map());\n const totalSpeedTrackerRef = useRef(createSpeedTracker());\n const fileLastSpeedRef = useRef<Map<string, number>>(new Map());\n const fileLastSpeedUpdateRef = useRef<Map<string, number>>(new Map());\n const lastTotalSpeedRef = useRef<number | undefined>(undefined);\n const lastTotalSpeedUpdateRef = useRef(0);\n\n const upload = useCallback(\n async (files: File[], resolveKey: (file: File) => string) => {\n const opts = optsRef.current;\n const api = opts.api ?? apiRef.current;\n if (!api)\n throw new Error(\n \"[better-s3] No S3Api client found. Pass `api` to useMultiUpload or wrap with <S3Provider>.\",\n );\n\n const items: Array<{\n id: string;\n file: File;\n objectKey: string;\n }> = [];\n const fileStates: MultiUploadFileState[] = [];\n const fileMap = new Map<string, File>();\n\n setState((s) => ({ ...s, phase: \"validating\", error: null }));\n\n if (opts.maxFiles && files.length > opts.maxFiles) {\n const msg = `Too many files. Maximum is ${opts.maxFiles}.`;\n setState((s) => ({ ...s, phase: \"error\", error: msg }));\n opts.onError?.(new Error(msg));\n return;\n }\n\n for (const file of files) {\n const validationError = validateFile(file, {\n accept: opts.accept,\n maxFileSize: opts.maxFileSize,\n });\n if (validationError) {\n const msg = `${file.name}: ${validationError}`;\n setState((s) => ({ ...s, phase: \"error\", error: msg }));\n opts.onError?.(new Error(msg));\n return;\n }\n }\n\n if (opts.beforeUpload) {\n const allowed = await opts.beforeUpload(files);\n if (!allowed) {\n setState((s) => ({\n ...s,\n phase: \"error\",\n error: \"Upload blocked by beforeUpload hook\",\n }));\n opts.onError?.(new Error(\"blocked\"));\n return;\n }\n }\n\n for (const file of files) {\n const id = generateId();\n const objectKey = resolveKey(file);\n items.push({ id, file, objectKey });\n fileMap.set(id, file);\n fileStates.push({\n id,\n fileName: file.name,\n fileSize: file.size,\n status: \"pending\",\n progress: { loaded: 0, total: file.size, percent: 0 },\n error: null,\n });\n }\n\n fileMapRef.current = fileMap;\n\n setState({\n phase: \"uploading\",\n files: fileStates,\n totalProgress: {\n loaded: 0,\n total: files.reduce((s, f) => s + f.size, 0),\n percent: 0,\n },\n error: null,\n });\n\n opts.onUploadStart?.(files);\n\n // Reset speed trackers for this batch\n fileSpeedTrackersRef.current.clear();\n for (const item of items) {\n fileSpeedTrackersRef.current.set(item.id, createSpeedTracker());\n }\n totalSpeedTrackerRef.current.reset();\n fileLastSpeedRef.current.clear();\n fileLastSpeedUpdateRef.current.clear();\n lastTotalSpeedRef.current = undefined;\n lastTotalSpeedUpdateRef.current = 0;\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n try {\n const results = await uploadFiles(\n api,\n items,\n {\n multipart: opts.multipart,\n multipartThreshold: opts.multipartThreshold,\n concurrentParts: opts.concurrentParts,\n concurrentFiles: opts.concurrentFiles,\n partSize: opts.partSize,\n retry: opts.retry,\n uploadStore: opts.uploadStore,\n },\n {\n onFileProgress: (id, progress) => {\n const tracker = fileSpeedTrackersRef.current.get(id);\n const rawSpeed = tracker ? tracker.update(progress.loaded) : 0;\n const now = Date.now();\n if (\n rawSpeed > 0 &&\n now - (fileLastSpeedUpdateRef.current.get(id) ?? 0) >= 500\n ) {\n fileLastSpeedRef.current.set(id, rawSpeed);\n fileLastSpeedUpdateRef.current.set(id, now);\n }\n const speed = fileLastSpeedRef.current.get(id);\n const p = speed ? { ...progress, speed } : progress;\n setState((s) => ({\n ...s,\n files: s.files.map((f) =>\n f.id === id ? { ...f, status: \"uploading\", progress: p } : f,\n ),\n }));\n const file = fileMap.get(id);\n if (file) opts.onFileProgress?.(file, p);\n },\n onFileSuccess: (id, result) => {\n setState((s) => ({\n ...s,\n files: s.files.map((f) =>\n f.id === id\n ? {\n ...f,\n status: \"success\",\n progress: {\n loaded: f.fileSize,\n total: f.fileSize,\n percent: 100,\n },\n }\n : f,\n ),\n }));\n const file = fileMap.get(id);\n if (file) opts.onFileSuccess?.(file, result);\n },\n onFileError: (id, error) => {\n setState((s) => ({\n ...s,\n files: s.files.map((f) =>\n f.id === id ? { ...f, status: \"error\", error } : f,\n ),\n }));\n const file = fileMap.get(id);\n if (file) opts.onFileError?.(file, error);\n },\n onTotalProgress: (progress) => {\n const rawSpeed = totalSpeedTrackerRef.current.update(\n progress.loaded,\n );\n const now = Date.now();\n if (\n rawSpeed > 0 &&\n now - lastTotalSpeedUpdateRef.current >= 1000\n ) {\n lastTotalSpeedRef.current = rawSpeed;\n lastTotalSpeedUpdateRef.current = now;\n }\n const speed = lastTotalSpeedRef.current;\n const p = speed ? { ...progress, speed } : progress;\n setState((s) => ({ ...s, totalProgress: p }));\n opts.onProgress?.(p);\n },\n },\n controller.signal,\n (file) => {\n const perFile = opts.getUploadOptions?.(file);\n if (!opts.uploadOptions) return perFile ?? {};\n return { ...opts.uploadOptions, ...perFile };\n },\n );\n\n const hasErrors = results.some((r) => r.status === \"error\");\n const successResults = results\n .filter((r) => r.result !== null)\n .map((r) => r.result!);\n\n setState((s) => ({\n ...s,\n phase: hasErrors ? \"error\" : \"success\",\n error: hasErrors\n ? `${results.filter((r) => r.status === \"error\").length} file(s) failed`\n : null,\n totalProgress: hasErrors\n ? s.totalProgress\n : {\n loaded: s.totalProgress.total,\n total: s.totalProgress.total,\n percent: 100,\n },\n }));\n\n if (!hasErrors) {\n await opts.onSuccess?.(successResults);\n }\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n if (!resettingRef.current) opts.onCancel?.();\n resettingRef.current = false;\n setState(INITIAL_STATE);\n return;\n }\n const message = err instanceof Error ? err.message : \"Upload failed\";\n setState((s) => ({ ...s, phase: \"error\", error: message }));\n opts.onError?.(err);\n } finally {\n abortRef.current = null;\n }\n },\n [],\n );\n\n const cancel = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n resettingRef.current = true;\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n return { ...state, upload, cancel, reset };\n}\n","\"use client\";\n\nimport { useRef, useState } from \"react\";\nimport type {\n UploadPhase,\n UploadProgress,\n UploadRequestOptions,\n} from \"../types\";\nimport { useUpload, type UseUploadOptions } from \"./use-upload\";\n\nexport type UseUploadControlsOptions = UseUploadOptions & {\n objectKey: string | ((file: File) => string);\n /** Static request options applied to the upload. */\n uploadOptions?: UploadRequestOptions;\n /** Per-upload request options override. */\n getUploadOptions?: (file: File) => UploadRequestOptions;\n};\n\nexport type UseUploadControlsReturn = {\n phase: UploadPhase;\n /** Info about the selected file. */\n fileInfo: { name: string; size: number } | null;\n progress: UploadProgress;\n error: string | null;\n isUploading: boolean;\n handleFiles: (files: FileList | null) => void;\n openFilePicker: () => void;\n cancel: () => void;\n /**\n * Soft-stop: preserves S3 parts and store entry so a future `upload()` can\n * resume. For non-resumable uploads, identical to `cancel()`.\n * See `UseUploadReturn.detach` for full semantics.\n */\n detach: () => void;\n reset: () => void;\n /** Spread on a hidden `<input>` element. */\n inputProps: {\n ref: React.RefObject<HTMLInputElement | null>;\n type: \"file\";\n accept?: string;\n hidden: true;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n };\n /** Spread on a container to enable drag-and-drop. */\n dropHandlers: {\n onDragOver: (e: React.DragEvent) => void;\n onDrop: (e: React.DragEvent) => void;\n };\n};\n\nexport function useUploadControls(\n options: UseUploadControlsOptions,\n): UseUploadControlsReturn {\n const single = useUpload(options);\n const inputRef = useRef<HTMLInputElement>(null);\n const [fileInfo, setFileInfo] = useState<{\n name: string;\n size: number;\n } | null>(null);\n\n const resolveKey = (file: File): string =>\n typeof options.objectKey === \"function\"\n ? options.objectKey(file)\n : options.objectKey;\n\n const handleFiles = async (files: FileList | null) => {\n const file = files?.[0];\n if (!file) return;\n setFileInfo({ name: file.name, size: file.size });\n await single.upload(file, resolveKey(file), {\n ...options.uploadOptions,\n ...options.getUploadOptions?.(file),\n });\n };\n\n return {\n phase: single.phase,\n fileInfo,\n progress: single.progress,\n error: single.error,\n isUploading: single.phase === \"uploading\",\n handleFiles,\n openFilePicker: () => inputRef.current?.click(),\n cancel: single.cancel,\n detach: single.detach,\n reset: () => {\n single.reset();\n setFileInfo(null);\n },\n inputProps: {\n ref: inputRef,\n type: \"file\",\n accept: options.accept?.join(\",\"),\n hidden: true,\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => {\n handleFiles(e.target.files);\n e.target.value = \"\";\n },\n },\n dropHandlers: {\n onDragOver: (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n },\n onDrop: (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (single.phase !== \"uploading\") handleFiles(e.dataTransfer.files);\n },\n },\n };\n}\n","\"use client\";\n\nimport { useRef } from \"react\";\nimport type {\n UploadProgress,\n UploadRequestOptions,\n MultiUploadFileState,\n MultiUploadPhase,\n} from \"../types\";\nimport { useMultiUpload, type UseMultiUploadOptions } from \"./use-multi-upload\";\n\nexport type UseMultiUploadControlsOptions = UseMultiUploadOptions & {\n objectKey: string | ((file: File) => string);\n};\n\nexport type UseMultiUploadControlsReturn = {\n phase: MultiUploadPhase;\n /** Per-file upload states. */\n files: MultiUploadFileState[];\n /** Aggregated progress across all files. */\n totalProgress: UploadProgress;\n error: string | null;\n isUploading: boolean;\n handleFiles: (files: FileList | null) => void;\n openFilePicker: () => void;\n cancel: () => void;\n reset: () => void;\n /** Spread on a hidden `<input>` element. */\n inputProps: {\n ref: React.RefObject<HTMLInputElement | null>;\n type: \"file\";\n multiple: true;\n accept?: string;\n hidden: true;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n };\n /** Spread on a container to enable drag-and-drop. */\n dropHandlers: {\n onDragOver: (e: React.DragEvent) => void;\n onDrop: (e: React.DragEvent) => void;\n };\n};\n\nexport function useMultiUploadControls(\n options: UseMultiUploadControlsOptions,\n): UseMultiUploadControlsReturn {\n const multi = useMultiUpload(options);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const resolveKey = (file: File): string =>\n typeof options.objectKey === \"function\"\n ? options.objectKey(file)\n : options.objectKey;\n\n const handleFiles = async (files: FileList | null) => {\n if (!files?.length) return;\n await multi.upload(Array.from(files), resolveKey);\n };\n\n return {\n phase: multi.phase,\n files: multi.files,\n totalProgress: multi.totalProgress,\n error: multi.error,\n isUploading: multi.phase === \"uploading\",\n handleFiles,\n openFilePicker: () => inputRef.current?.click(),\n cancel: multi.cancel,\n reset: multi.reset,\n inputProps: {\n ref: inputRef,\n type: \"file\",\n multiple: true,\n accept: options.accept?.join(\",\"),\n hidden: true,\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => {\n handleFiles(e.target.files);\n e.target.value = \"\";\n },\n },\n dropHandlers: {\n onDragOver: (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n },\n onDrop: (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (multi.phase !== \"uploading\") handleFiles(e.dataTransfer.files);\n },\n },\n };\n}\n","\"use client\";\n\nimport { useCallback, useContext, useState } from \"react\";\nimport type { S3Api } from \"../types/s3-api\";\nimport { S3Context } from \"../s3-provider\";\nimport { useLiveRef } from \"../internal-helpers\";\n\nexport type { DownloadPhase, DownloadHooks } from \"../types/download\";\n\nimport type { DownloadPhase, DownloadHooks } from \"../types/download\";\n\nexport type UseDownloadOptions = DownloadHooks & {\n /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */\n api?: S3Api;\n /** Target bucket (overrides server default) */\n bucket?: string;\n};\n\nexport type UseDownloadState = {\n phase: DownloadPhase;\n error: string | null;\n /** Presigned URL — set after a successful presign, cleared on reset */\n url: string | null;\n /** Validity window in seconds for the presigned URL */\n expiresIn: number | null;\n};\n\nexport type UseDownloadReturn = UseDownloadState & {\n download: (key: string, downloadName?: string) => Promise<void>;\n /** Fetch the presigned URL without triggering a browser download — for headless use */\n presign: (\n key: string,\n downloadName?: string,\n ) => Promise<{ url: string; expiresIn: number } | null>;\n reset: () => void;\n};\n\nconst INITIAL_STATE: UseDownloadState = {\n phase: \"idle\",\n error: null,\n url: null,\n expiresIn: null,\n};\n\nexport function useDownload(options: UseDownloadOptions): UseDownloadReturn {\n const [state, setState] = useState<UseDownloadState>(INITIAL_STATE);\n const contextApi = useContext(S3Context);\n const optsRef = useLiveRef(options);\n const apiRef = useLiveRef(contextApi);\n\n const presign = useCallback(async (key: string, downloadName?: string) => {\n const opts = optsRef.current;\n const api = opts.api ?? apiRef.current;\n if (!api)\n throw new Error(\n \"[better-s3] No S3Api client found. Pass `api` to useDownload or wrap with <S3Provider>.\",\n );\n setState({ phase: \"presigning\", error: null, url: null, expiresIn: null });\n try {\n const result = await api.download(key, {\n fileName: downloadName,\n bucket: opts.bucket,\n });\n setState({\n phase: \"idle\",\n error: null,\n url: result.url,\n expiresIn: result.expiresIn,\n });\n return { url: result.url, expiresIn: result.expiresIn };\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Download failed\";\n setState({ phase: \"error\", error: message, url: null, expiresIn: null });\n opts.onError?.(key, err);\n return null;\n }\n }, []);\n\n const download = useCallback(\n async (key: string, downloadName?: string) => {\n const opts = optsRef.current;\n if (opts.beforeDownload) {\n const allowed = await opts.beforeDownload(key);\n if (!allowed) {\n setState({\n phase: \"error\",\n error: \"Download blocked by beforeDownload hook\",\n url: null,\n expiresIn: null,\n });\n opts.onError?.(key, new Error(\"blocked\"));\n return;\n }\n }\n const result = await presign(key, downloadName);\n if (!result) return;\n window.location.href = result.url;\n opts.onInitiated?.(key);\n },\n [presign],\n );\n\n const reset = useCallback(() => setState(INITIAL_STATE), []);\n\n return { ...state, download, presign, reset };\n}\n","\"use client\";\n\nimport { useCallback, useContext, useRef, useState } from \"react\";\nimport type { S3Api } from \"../types/s3-api\";\nimport { S3Context } from \"../s3-provider\";\nimport { parseContentDispositionFilename } from \"../helpers\";\nimport { createSpeedTracker } from \"../helpers/speed-tracker\";\nimport type { FetchDownloadPhase, FetchDownloadHooks } from \"../types/download\";\nimport type { UploadProgress } from \"../types/upload\";\nimport { useLiveRef } from \"../internal-helpers\";\n\nexport type {\n FetchDownloadPhase,\n FetchDownloadProgress,\n FetchDownloadHooks,\n} from \"../types/download\";\n\nexport type UseFetchDownloadOptions = FetchDownloadHooks & {\n /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */\n api?: S3Api;\n /** Target bucket (overrides server default) */\n bucket?: string;\n};\n\nexport type UseFetchDownloadState = {\n phase: FetchDownloadPhase;\n progress: UploadProgress;\n error: string | null;\n fileName: string | null;\n fileSize: number | null;\n};\n\nexport type UseFetchDownloadReturn = UseFetchDownloadState & {\n download: (key: string, downloadName?: string) => Promise<void>;\n cancel: () => void;\n reset: () => void;\n};\n\nconst INITIAL_PROGRESS: UploadProgress = { loaded: 0, total: 0, percent: 0 };\n\nconst INITIAL_STATE: UseFetchDownloadState = {\n phase: \"idle\",\n progress: INITIAL_PROGRESS,\n error: null,\n fileName: null,\n fileSize: null,\n};\n\nexport function useFetchDownload(\n options: UseFetchDownloadOptions,\n): UseFetchDownloadReturn {\n const [state, setState] = useState<UseFetchDownloadState>(INITIAL_STATE);\n const contextApi = useContext(S3Context);\n const optsRef = useLiveRef(options);\n const apiRef = useLiveRef(contextApi);\n const abortRef = useRef<AbortController | null>(null);\n const resettingRef = useRef(false);\n const speedTrackerRef = useRef(createSpeedTracker());\n const lastSpeedRef = useRef<number | undefined>(undefined);\n const lastSpeedUpdateRef = useRef(0);\n\n const download = useCallback(async (key: string, downloadName?: string) => {\n const fallback = key.split(\"/\").pop() ?? key;\n const opts = optsRef.current;\n const api = opts.api ?? apiRef.current;\n if (!api)\n throw new Error(\n \"[better-s3] No S3Api client found. Pass `api` to useFetchDownload or wrap with <S3Provider>.\",\n );\n\n if (opts.beforeDownload) {\n const allowed = await opts.beforeDownload(key);\n if (!allowed) {\n setState((s) => ({\n ...s,\n phase: \"error\",\n error: \"Download blocked by beforeDownload hook\",\n }));\n opts.onError?.(key, new Error(\"blocked\"), \"presigning\");\n return;\n }\n }\n\n setState({\n phase: \"presigning\",\n progress: INITIAL_PROGRESS,\n error: null,\n fileName: downloadName ?? null,\n fileSize: null,\n });\n\n try {\n const { url } = await api.download(key, {\n fileName: downloadName,\n bucket: opts.bucket,\n });\n setState((s) => ({ ...s, phase: \"downloading\" }));\n opts.onDownloadStart?.(key);\n\n speedTrackerRef.current.reset();\n lastSpeedRef.current = undefined;\n lastSpeedUpdateRef.current = 0;\n const controller = new AbortController();\n abortRef.current = controller;\n\n const res = await fetch(url, { signal: controller.signal });\n if (!res.ok) {\n throw new Error(\n res.status === 404\n ? \"File not found\"\n : `Download failed (${res.status})`,\n );\n }\n\n const contentLength = Number(res.headers.get(\"content-length\") || 0);\n const name =\n downloadName ??\n parseContentDispositionFilename(\n res.headers.get(\"content-disposition\"),\n fallback,\n );\n setState((s) => ({\n ...s,\n fileName: name,\n fileSize: contentLength || null,\n }));\n\n const reader = res.body?.getReader();\n if (!reader) throw new Error(\"ReadableStream not supported\");\n\n const chunks: BlobPart[] = [];\n let loaded = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n loaded += value.byteLength;\n const percent =\n contentLength > 0 ? Math.round((loaded / contentLength) * 100) : 0;\n const rawSpeed = speedTrackerRef.current.update(loaded);\n const now = Date.now();\n if (rawSpeed > 0 && now - lastSpeedUpdateRef.current >= 500) {\n lastSpeedRef.current = rawSpeed;\n lastSpeedUpdateRef.current = now;\n }\n const speed = lastSpeedRef.current;\n const progress: UploadProgress = {\n loaded,\n total: contentLength,\n percent,\n ...(speed && { speed }),\n };\n setState((s) => ({ ...s, progress }));\n opts.onProgress?.(key, progress);\n }\n\n const blob = new Blob(chunks);\n const blobUrl = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = blobUrl;\n anchor.download = name ?? fallback;\n anchor.click();\n URL.revokeObjectURL(blobUrl);\n\n setState((s) => ({\n ...s,\n phase: \"success\",\n fileSize: blob.size,\n progress: { loaded: blob.size, total: blob.size, percent: 100 },\n }));\n await opts.onSuccess?.(key, name ?? fallback);\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n if (!resettingRef.current) opts.onCancel?.(key);\n resettingRef.current = false;\n setState(INITIAL_STATE);\n return;\n }\n const message = err instanceof Error ? err.message : \"Download failed\";\n setState((s) => ({ ...s, phase: \"error\", error: message }));\n opts.onError?.(key, err, \"downloading\");\n } finally {\n abortRef.current = null;\n }\n }, []);\n\n const cancel = useCallback(() => {\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n resettingRef.current = true;\n abortRef.current?.abort();\n setState(INITIAL_STATE);\n }, []);\n\n return { ...state, download, cancel, reset };\n}\n","\"use client\";\n\nimport { useCallback, useContext, useRef, useState } from \"react\";\nimport type { S3Api } from \"../types/s3-api\";\nimport { S3Context } from \"../s3-provider\";\nimport type { DeletePhase, DeleteHooks } from \"../types\";\nimport { useLiveRef } from \"../internal-helpers\";\n\nexport type UseDeleteOptions = DeleteHooks & {\n /** S3Api client. Optional when an `<S3Provider>` is present in the tree. */\n api?: S3Api;\n /** Target bucket (overrides server default) */\n bucket?: string;\n};\n\nexport type UseDeleteState = {\n phase: DeletePhase;\n error: string | null;\n};\n\nexport type UseDeleteReturn = UseDeleteState & {\n requestDelete: (key: string) => void;\n confirmDelete: () => Promise<void>;\n cancelDelete: () => void;\n reset: () => void;\n pendingKey: string | null;\n};\n\ntype InternalState = {\n phase: DeletePhase;\n error: string | null;\n pendingKey: string | null;\n};\n\nconst INITIAL_STATE: InternalState = {\n phase: \"idle\",\n error: null,\n pendingKey: null,\n};\n\nexport function useDelete(options: UseDeleteOptions): UseDeleteReturn {\n const [state, setState] = useState<InternalState>(INITIAL_STATE);\n const contextApi = useContext(S3Context);\n const optsRef = useLiveRef(options);\n const apiRef = useLiveRef(contextApi);\n const pendingKeyRef = useRef<string | null>(null);\n\n const requestDelete = useCallback((key: string) => {\n pendingKeyRef.current = key;\n setState({ phase: \"confirming\", error: null, pendingKey: key });\n }, []);\n\n const confirmDelete = useCallback(async () => {\n const key = pendingKeyRef.current;\n if (!key) return;\n const opts = optsRef.current;\n const api = opts.api ?? apiRef.current;\n if (!api)\n throw new Error(\n \"[better-s3] No S3Api client found. Pass `api` to useDelete or wrap with <S3Provider>.\",\n );\n\n if (opts.beforeDelete) {\n const allowed = await opts.beforeDelete(key);\n if (!allowed) {\n setState({\n phase: \"error\",\n error: \"Delete blocked by beforeDelete hook\",\n pendingKey: null,\n });\n opts.onError?.(key, new Error(\"blocked\"), \"confirming\");\n pendingKeyRef.current = null;\n return;\n }\n }\n\n setState((s) => ({ ...s, phase: \"deleting\", error: null }));\n opts.onDeleteStart?.(key);\n\n try {\n await api.delete(key, { bucket: opts.bucket });\n pendingKeyRef.current = null;\n setState({ phase: \"success\", error: null, pendingKey: null });\n await opts.onSuccess?.(key);\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Delete failed\";\n setState((s) => ({ ...s, phase: \"error\", error: message }));\n opts.onError?.(key, err, \"deleting\");\n }\n }, []);\n\n const cancelDelete = useCallback(() => {\n pendingKeyRef.current = null;\n setState(INITIAL_STATE);\n }, []);\n\n const reset = useCallback(() => {\n pendingKeyRef.current = null;\n setState(INITIAL_STATE);\n }, []);\n\n return {\n phase: state.phase,\n error: state.error,\n pendingKey: state.pendingKey,\n requestDelete,\n confirmDelete,\n cancelDelete,\n reset,\n };\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeps a ref in sync with the latest value on every render.
|
|
3
|
+
*
|
|
4
|
+
* Use inside `useCallback(fn, [])` to read the latest prop / option value
|
|
5
|
+
* without making the callback depend on it (stale-closure-free stable refs).
|
|
6
|
+
*
|
|
7
|
+
* @internal — not part of the public API.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useLiveRef<T>(value: T): import("react").RefObject<T>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { S3Api } from "./types/s3-api";
|
|
3
|
+
/**
|
|
4
|
+
* Internal context — use `S3Provider` to supply and `useS3Client` to consume.
|
|
5
|
+
* Exported so hooks can call `useContext(S3Context)` directly without throwing
|
|
6
|
+
* when `api` is passed explicitly.
|
|
7
|
+
*/
|
|
8
|
+
export declare const S3Context: import("react").Context<S3Api | null>;
|
|
9
|
+
/**
|
|
10
|
+
* Provides an `S3Api` client to all child hooks and UI components.
|
|
11
|
+
*
|
|
12
|
+
* Wrap your app (or a sub-tree) once; hooks no longer need `api` passed
|
|
13
|
+
* individually.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* // With @better-s3/server:
|
|
18
|
+
* import { createS3Api } from "@better-s3/server";
|
|
19
|
+
* import { S3Provider } from "@better-s3/react";
|
|
20
|
+
*
|
|
21
|
+
* const s3Client = createS3Api("/api/s3");
|
|
22
|
+
*
|
|
23
|
+
* export function Providers({ children }: { children: React.ReactNode }) {
|
|
24
|
+
* return <S3Provider client={s3Client}>{children}</S3Provider>;
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* // With a custom server (use createS3Client for a compatible fetch client):
|
|
28
|
+
* import { createS3Client, S3Provider } from "@better-s3/react";
|
|
29
|
+
*
|
|
30
|
+
* const s3Client = createS3Client("/api/my-s3");
|
|
31
|
+
*
|
|
32
|
+
* export function Providers({ children }: { children: React.ReactNode }) {
|
|
33
|
+
* return <S3Provider client={s3Client}>{children}</S3Provider>;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function S3Provider({ client, children, }: {
|
|
38
|
+
client: S3Api;
|
|
39
|
+
children: ReactNode;
|
|
40
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the `S3Api` client from the nearest `S3Provider`.
|
|
43
|
+
* Throws if called outside a provider and no `api` prop was given to the hook.
|
|
44
|
+
*
|
|
45
|
+
* @throws if no `S3Provider` is found in the tree.
|
|
46
|
+
*/
|
|
47
|
+
export declare function useS3Client(): S3Api;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UploadStore } from "../types/upload-store";
|
|
2
|
+
/**
|
|
3
|
+
* Default `UploadStore` implementation backed by `localStorage`.
|
|
4
|
+
* Stores one pending upload per S3 object key.
|
|
5
|
+
*
|
|
6
|
+
* Falls back silently when `localStorage` is unavailable (SSR, private
|
|
7
|
+
* browsing with full quota, or environments without a `window` object).
|
|
8
|
+
*/
|
|
9
|
+
export declare function createLocalStorageStore(): UploadStore;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { UploadStore } from "../types/upload-store";
|
|
2
|
+
/**
|
|
3
|
+
* In-memory `UploadStore` — safe for SSR and server-component environments.
|
|
4
|
+
*
|
|
5
|
+
* State is cleared on page reload. Useful as a fallback, for testing, or
|
|
6
|
+
* when you want session-scoped resume without touching `localStorage`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const store = createMemoryStore();
|
|
11
|
+
* useUpload({ api, uploadStore: store });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function createMemoryStore(): UploadStore;
|