import type { Body, MultipartOptions, RetryOptions, UploadProgress, UploadResult } from "../index.js"; /** * A serializable handle to a provider-side upload session, discriminated by * provider family. Produced by {@link UploadControl.toJSON} once a session is * established; persist it (disk, `localStorage`, a DB) and rehydrate it with * {@link UploadControl.from} to resume the upload in a later process. * * The shape differs per provider because the resume primitive does: S3 and * Azure track discrete parts/blocks (so the part size is pinned in the token — * resumed part boundaries must line up), while GCS, OneDrive, and Dropbox track * a byte offset against an opaque session URL/id. */ export type ResumableUploadSession = { provider: "s3"; bucket: string; key: string; uploadId: string; partSize: number; } | { provider: "gcs"; bucket: string; key: string; uri: string; } | { provider: "google-drive"; key: string; uri: string; } | { provider: "azure"; container: string; blob: string; blockSize: number; contentType: string; } | { provider: "onedrive"; itemPath: string; uploadUrl: string; } | { provider: "dropbox"; path: string; sessionId: string; offset: number; contentType: string; } | { provider: "vercel-blob"; key: string; storageKey: string; uploadId: string; partSize: number; contentType: string; parts: PartMeta[]; } | { provider: "fs"; key: string; tempPath: string; contentType: string; } | { provider: "memory"; key: string; uploadId: string; contentType: string; } | { provider: "ftp"; key: string; } | { provider: "sftp"; key: string; } | { provider: "bun-s3"; key: string; uploadId: string; contentType: string; } | { provider: "supabase"; key: string; uri: string; contentType: string; } | { provider: "appwrite"; key: string; fileId: string; contentType: string; offset: number; } | { provider: "cloudinary"; key: string; uploadId: string; contentType: string; offset: number; } | { provider: "box"; key: string; uploadId: string; contentType: string; }; /** The lifecycle state of an {@link UploadControl}. */ export type UploadControlStatus = "idle" | "uploading" | "paused" | "completed" | "aborted" | "error"; /** * A handle for pausing, resuming, aborting, and serializing a single * {@link UploadOptions.control resumable upload}. Construct one and pass it to * `upload()`; the SDK populates {@link session} as soon as the provider session * is created, so `pause()` then `toJSON()` captures resumable state even before * the first chunk lands. * * A control drives one upload. To resume in a new process, persist * `toJSON()` and rehydrate with {@link UploadControl.from}. */ export declare class UploadControl { constructor(); /** * Rebuild a control pre-loaded with a persisted {@link toJSON} token, ready * to resume. Pass it to `upload()` with the same body — the SDK discovers * what already landed server-side and uploads only the rest. */ static from(session: ResumableUploadSession): UploadControl; /** Lifecycle state — see {@link UploadControlStatus}. */ get status(): UploadControlStatus; /** Cumulative bytes confirmed uploaded so far. */ get loaded(): number; /** Total bytes to upload, once known. */ get total(): number | undefined; /** The current session token, or `undefined` before one is established. */ get session(): ResumableUploadSession | undefined; /** The session token to persist for a later {@link UploadControl.from} resume. */ toJSON(): ResumableUploadSession | undefined; /** * Stop dispatching new chunks. In-flight chunks settle; the `upload()` * promise stays pending until {@link resume}. The session is preserved, so * you can `toJSON()` and persist it here. */ pause(): void; /** Continue a paused upload. */ resume(): void; /** * Cancel the upload **and** discard the provider-side session (a partial * upload left behind by `pause()` can be billed/retained by the provider). * The `upload()` promise rejects with an aborted {@link FilesError}. Terminal: * the session can no longer be resumed. * * To cancel but *keep* the session for a later resume, abort via * {@link OperationOptions.signal} instead. */ abort(reason?: unknown): Promise; } /** A completed part/block, tracked so the upload can be finalized. */ export interface PartMeta { partNumber: number; size: number; /** Entity tag, where the provider returns one per part (S3). */ etag?: string; } /** Per-upload knobs an adapter's {@link Adapter.resumableUpload} receives. */ export interface ResumableDriverOptions { multipart?: boolean | MultipartOptions; cacheControl?: string; metadata?: Record; } interface ResumableDriverBase { /** * Bytes per part/chunk, finalized by {@link begin} / {@link adopt}. Pinned in * the token for part-based providers so resumed boundaries line up. */ readonly partSize: number; /** Create the provider session and return its serializable token. */ begin(meta: { total: number; contentType: string; }): Promise; /** Resume: load (and validate) a persisted token. Throws on a mismatch. */ adopt(session: ResumableUploadSession): void; /** Finalize the upload into an {@link UploadResult}. */ complete(parts: PartMeta[]): Promise; /** Discard the provider session and any uploaded-but-uncommitted data. */ discard(): Promise; } /** Parallel, part-numbered providers (S3, Azure block blobs). */ export interface PartsResumableDriver extends ResumableDriverBase { readonly mode: "parts"; /** Discover which parts already landed server-side (for resume). */ probe(): Promise<{ committedParts: PartMeta[]; }>; uploadPart(part: { partNumber: number; data: Uint8Array; signal?: AbortSignal; }): Promise; } /** Sequential, offset-based providers (GCS, OneDrive, Dropbox). */ export interface OffsetResumableDriver extends ResumableDriverBase { readonly mode: "offset"; /** Discover the next byte the server expects (for resume). */ probe(): Promise<{ nextOffset: number; }>; uploadAt(chunk: { offset: number; data: Uint8Array; isLast: boolean; total: number; signal?: AbortSignal; }): Promise<{ nextOffset: number; }>; } export type ResumableDriver = PartsResumableDriver | OffsetResumableDriver; interface ByteSource { readonly size: number; slice(start: number, end: number): Promise; } /** * Wrap a {@link Body} so the orchestrator can read any `[start, end)` slice. * Buffered bodies slice synchronously; `Blob`/`File` slice lazily so only the * parts in flight are held in memory. A `ReadableStream` is rejected — it can't * be re-read, which both pause/resume and cross-process resume require. */ export declare const toByteSource: (body: Body) => ByteSource; export interface RunResumableOptions { driver: ResumableDriver; body: Body; control: UploadControl; multipart?: boolean | MultipartOptions; onProgress?: (progress: UploadProgress) => void; retries?: RetryOptions; timeout?: number; /** External abort signals (client default + per-call). */ signals: AbortSignal[]; contentTypeHint?: string; } /** * Drive a {@link ResumableDriver} to completion under an {@link UploadControl}: * establish (or resume) the session, slice and dispatch chunks honoring * pause/abort, retry per chunk, report progress, and finalize. Returns the * provider's {@link UploadResult}. */ export declare const runResumableUpload: (opts: RunResumableOptions) => Promise; export {}; //# sourceMappingURL=resumable.d.ts.map