diff --git a/.changeset/two-ducks-act.md b/.changeset/two-ducks-act.md new file mode 100644 index 000000000..553b122a1 --- /dev/null +++ b/.changeset/two-ducks-act.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/react-renterd': minor +--- + +Add useMultipartUploadCreate, useMultipartUploadComplete, useMultipartUploadAbort, useMultipartUploadAddPart, useMultipartUploadChunk, useMultipartUploadListUploads, useMultipartUploadListParts. diff --git a/libs/react-renterd/src/bus.ts b/libs/react-renterd/src/bus.ts index 500bdb382..87db25b06 100644 --- a/libs/react-renterd/src/bus.ts +++ b/libs/react-renterd/src/bus.ts @@ -29,7 +29,9 @@ import { Host, HostSettings, Obj, + PartialSlab, SiacoinElement, + SlabSlice, WalletTransaction, } from './siaTypes' @@ -838,3 +840,159 @@ export function useMetricsWallet( // hostKey: string // origin: string // } + +// multipart + +export type MultipartUploadCreatePayload = { + path: string + bucket: string + generateKey: boolean + key?: string +} + +export function useMultipartUploadCreate( + args?: HookArgsCallback< + void, + MultipartUploadCreatePayload, + { uploadID: string } + > +) { + return usePostFunc( + { ...args, route: '/bus/multipart/create' }, + async (mutate) => { + mutate((key) => { + return key.startsWith('/bus/multipart') + }) + } + ) +} + +export type MultipartUploadCompletePart = { + partNumber: number + eTag: string +} + +export type MultipartUploadCompletePayload = { + path: string + bucket: string + uploadID: string + parts: MultipartUploadCompletePart[] +} + +export function useMultipartUploadComplete( + args?: HookArgsCallback +) { + return usePostFunc( + { ...args, route: '/bus/multipart/complete' }, + async (mutate) => { + mutate((key) => { + return key.startsWith('/bus/multipart') + }) + } + ) +} + +export type MultipartUploadAbortPayload = { + path: string + bucket: string + uploadID: string +} + +export function useMultipartUploadAbort( + args?: HookArgsCallback +) { + return usePostFunc( + { ...args, route: '/bus/multipart/abort' }, + async (mutate) => { + mutate((key) => { + return key.startsWith('/bus/multipart') + }) + } + ) +} + +export type MultipartUploadListPartsPayload = { + bucket: string + path: string + uploadID: string + partNumberMarker?: number + limit?: number +} + +export type MultipartUploadListPartsResponse = { + hasMore: boolean + nextMarker?: number + parts: { + partNumber: number + lastModified: string + eTag: string + size: number + }[] +} + +export function useMultipartUploadListParts( + args: HookArgsWithPayloadSwr< + void, + MultipartUploadListPartsPayload, + MultipartUploadListPartsResponse + > +) { + return usePostSwr({ + ...args, + route: '/bus/multipart/listparts', + }) +} + +export type MultipartUploadListUploadsPayload = { + bucket: string + prefix?: string + pathMarker?: string + uploadIDMarker?: string + limit?: number +} + +export type MultipartUploadListUploadsResponse = { + uploads: { + path: string + uploadID: string + createdAt: string + }[] +} + +export function useMultipartUploadListUploads( + args: HookArgsWithPayloadSwr< + void, + MultipartUploadListUploadsPayload, + MultipartUploadListUploadsResponse + > +) { + return usePostSwr({ + ...args, + route: '/bus/multipart/listuploads', + }) +} + +export type MultipartUploadAddPartPayload = { + path: string + bucket: string + uploadID: string + eTag: string + partNumber: number + contractSet?: string + partialSlabs?: PartialSlab[] + slices?: SlabSlice[] + usedContracts?: Contract[] +} + +export function useMultipartUploadAddPart( + args?: HookArgsCallback +) { + return usePostFunc( + { ...args, route: '/bus/multipart/part' }, + async (mutate) => { + mutate((key) => { + return key.startsWith('/bus/multipart/listparts') + }) + } + ) +} diff --git a/libs/react-renterd/src/siaTypes.ts b/libs/react-renterd/src/siaTypes.ts index 21357f595..a7f1c1f15 100644 --- a/libs/react-renterd/src/siaTypes.ts +++ b/libs/react-renterd/src/siaTypes.ts @@ -87,6 +87,12 @@ export type Sector = { root: string } +export type PartialSlab = { + key: EncryptionKey + offset: number + length: number +} + export type Slab = { health: number key: EncryptionKey diff --git a/libs/react-renterd/src/worker.ts b/libs/react-renterd/src/worker.ts index 3315edf63..9cc21a30d 100644 --- a/libs/react-renterd/src/worker.ts +++ b/libs/react-renterd/src/worker.ts @@ -55,6 +55,35 @@ export function useObjectUpload( ) } +export type MultipartUploadChunkParams = { + key: string + uploadid: string + partnumber: number + offset: number + bucket?: string + contractset?: string + minshards?: number + totalshards?: number +} + +export function useMultipartUploadChunk( + args?: HookArgsCallback +) { + return usePutFunc({ + ...args, + config: { + ...args?.config, + axios: { + ...args?.config?.axios, + headers: { + 'Content-Type': 'multipart/form-data', + }, + }, + }, + route: '/worker/multipart/:key', + }) +} + export type RhpScanRequest = { hostKey: string hostIP: string