import type { Body, BulkError, BulkOptions, ByteRange, DeleteManyOptions, DeleteManyResult, MultipartOptions } from "../index.js"; import { FilesError } from "./errors.js"; /** * Default expiry, in seconds, for adapter `url()` and signed-upload helpers * when neither a per-call `expiresIn` nor an adapter-level * `defaultUrlExpiresIn` is set. 1 hour: long enough for normal browser * flows, short enough that an accidentally-leaked URL stops working before * the day is out. */ export declare const DEFAULT_URL_EXPIRES_IN = 3600; /** * Concatenate a public base URL with a key. Tolerates a single trailing * slash on the base. The key is URL-encoded so it's safe to embed in a URL path. * Pass raw keys — this function handles encoding. Passing a pre-encoded key * causes double-encoding (e.g. `%20` becomes `%2520`). */ export declare const joinPublicUrl: (base: string, key: string) => string; export interface UrlStrategyInput { publicBaseUrl?: string; responseContentDisposition?: string; } /** * Resolve which path `url()` should take when the adapter has both a * `publicBaseUrl` (unsigned, permanent) and a signing primitive available. * * - `"public"` — return `${publicBaseUrl}/${key}` unsigned. * - `"sign"` — mint a presigned/SAS URL. * * `responseContentDisposition` always forces `"sign"`, even when * `publicBaseUrl` is configured: a permanent CDN URL has no signature in * which to bind the override, and silently dropping the override is a * stored-XSS regression on user-uploaded HTML/SVG. The override wins. * * Adapters with three or more URL strategies (e.g. Supabase's * public/getPublicUrl/signed split, R2's binding/hybrid/throw split) keep * their own logic — this helper is for the common two-state case. */ export declare const resolveUrlStrategy: (input: UrlStrategyInput) => "public" | "sign"; /** * Render a {@link ByteRange} as an HTTP `Range` header value — `bytes=0-99`, * or `bytes=100-` when no `end` was given (read to EOF). Suitable for the S3 * `Range` request parameter and for any `fetch`-based adapter's headers. */ export declare const httpRangeHeader: (range: ByteRange) => string; /** * Number of bytes a range covers against a known full object size, clamped so * an `end` past EOF (or a `start` at/after EOF) can't report a negative or * oversized length. Used by the stream paths, which surface a `size` up front * without reading the body. */ export declare const rangedSize: (fullSize: number, range: ByteRange) => number; /** * Headers carrying an HTTP `Range` request for `range`, or `undefined` when no * range was asked for. Spread into a `fetch` init (or any SDK that forwards * request headers). */ export declare const rangeRequestHeaders: (range: ByteRange | undefined) => { Range: string; } | undefined; /** * Size to report for a streamed, ranged fetch. Prefers the `Content-Length` of * the `206` response (the exact slice length the server sent), falling back to * computing it from the known full object size when the header is absent. */ export declare const rangedResponseSize: (contentLength: string | null, fullSize: number, range: ByteRange) => number; /** * Confirm a response to a ranged request actually returned the slice * (`206 Partial Content`) rather than the whole object (`200`, what a server * sends when it ignores `Range`). Throws so a caller asking for a slice never * silently receives — and pays to transfer — the entire object. * * Only for adapters fetching an arbitrary URL (CDN / presigned / temporary * link), where range support isn't guaranteed. Provider-native range APIs * (S3, GCS, Azure, the Graph/Drive content endpoints, the R2 binding) honor it * by contract and skip this check. */ export declare const assertRangeHonored: (status: number, providerLabel: string) => void; /** * Guard for folder-based providers that only understand `/` as a path * separator (the SaaS stores: Vercel Blob, Netlify Blobs, Supabase, Dropbox, * Box, OneDrive). They advertise `supportsDelimiter` but can't honor an * arbitrary delimiter the way the object stores can, so reject anything else * loudly rather than silently treating it as `/`. */ export declare const assertSlashDelimiter: (providerLabel: string, delimiter: string) => void; export interface NormalizedBody { /** * The body as either a fully-buffered `Uint8Array` (when the source had a * known length) or a `ReadableStream` (when it didn't). * Adapters whose SDK accepts neither shape natively (Node `Buffer`, * `ArrayBuffer`, Node `Readable`) should convert this themselves — * branching on `data instanceof ReadableStream` is one line each. */ data: Uint8Array | ReadableStream; contentType: string; /** * Bytes the adapter can declare up-front. Absent when the body is a * `ReadableStream` of unknown length — in that case, adapters that need a * size in their response (`UploadResult.size`) typically do a follow-up * `head()` after upload to surface the authoritative value. */ contentLength?: number; } /** * Convert a {@link Body} into a uniform shape adapters can hand to their * underlying SDK. * * `contentTypeHint` always wins. Otherwise the type is inferred: * - strings → `"text/plain; charset=utf-8"` * - Blobs → `blob.type` if non-empty, else `"application/octet-stream"` * - everything else → `"application/octet-stream"` */ export declare const normalizeBody: (body: Body, contentTypeHint?: string) => Promise; export interface ErrorExtract { /** * Provider-specific error identifier (the string code from the response * body or SDK error class — e.g. `"NoSuchKey"`, `"BlobNotFound"`, * `"Duplicate"`). Matched against the sets in {@link ErrorMapperConfig.codes}. */ code?: string; /** * HTTP status code. Matched against the standard buckets — 404 → * NotFound, 401/403 → Unauthorized, 409/412 → Conflict. */ status?: number; message?: string; } export interface ErrorMapperConfig { /** Used as the fallback `Provider`-code message when the source error has none. */ providerLabel: string; /** * Storage-error code strings that should map to each `FilesErrorCode`. * Pass empty `Set`s for providers that classify only by HTTP status. */ codes: { notFound: ReadonlySet; unauthorized: ReadonlySet; conflict: ReadonlySet; }; /** * Pull a `{ code, status, message }` triple out of an unknown provider * error. Different SDKs put these on different fields (e.g. AWS uses * `$metadata.httpStatusCode`, Azure uses `details.errorCode`, Supabase * stringifies its code under `statusCode`) — encode that variance here. */ extract: (err: unknown) => ErrorExtract; } /** * Build a `(err) => FilesError` mapper from a per-provider config. The * returned function: * - returns `err` unchanged if it's already a {@link FilesError} (so * adapters can re-throw their own programmatic errors without * re-wrapping) * - extracts code/status/message via `config.extract` * - classifies via the provider's code sets and the standard HTTP status * buckets * - preserves the original error as `cause` */ export declare const makeErrorMapper: (config: ErrorMapperConfig) => ((err: unknown) => FilesError); /** * Standard `exists()` scaffold for providers whose "does this object exist?" * probe is "attempt a metadata lookup and classify NotFound specially". * * The `probe` should be the cheapest provider call that can distinguish * present vs missing for the adapter. Successful probes return `true`; * mapped `NotFound` errors return `false`; every other failure is rethrown. */ export declare const existsByProbe: (probe: () => Promise, mapError: (err: unknown) => FilesError) => Promise; /** * Drain a `ReadableStream` into a single concatenated `Uint8Array`. * Used by adapters whose SDK lacks a streaming upload form and by * {@link createStoredFile} when a stream body is read into a buffering * accessor. */ export declare const collectStream: (stream: ReadableStream) => Promise; /** * Synchronously determine a body's byte length when it's cheap to know. * Returns `undefined` for a `ReadableStream`, whose length is unknown until * drained. Used to surface a `total` in upload-progress reports without * consuming the body. */ export declare const byteLengthOf: (body: Body) => number | undefined; /** * Wrap a byte stream so it reports cumulative progress as it's consumed. The * returned stream yields the same chunks in the same order; `onChunk` is * called with the running byte total after each chunk is forwarded. Pulls * lazily, so the total tracks what the downstream reader (the adapter) has * actually drained — which approximates upload progress for streaming * adapters. Used to drive `onProgress` for `ReadableStream` bodies without * buffering them. */ export declare const countingStream: (stream: ReadableStream, onChunk: (loaded: number) => void) => ReadableStream; /** * Whether an upload caller opted into multipart — a truthy boolean or a * {@link MultipartOptions} object. Shared by the adapters that branch on it. */ export declare const isMultipartRequested: (multipart: boolean | MultipartOptions | undefined) => boolean; /** * Round a multipart `partSize` to a chunk size valid for `@google-cloud/storage` * resumable uploads — a multiple of 256 KiB, never below one unit. Shared by the * GCS and Firebase Storage adapters. Returns `undefined` when no `partSize` was * supplied (or `multipart` was a bare boolean) so the SDK default applies. */ export declare const resumableChunkSize: (multipart: boolean | MultipartOptions | undefined) => number | undefined; export declare const deleteManyWithFallback: (keys: string[], remove: (key: string) => Promise, opts?: DeleteManyOptions, mapError?: (error: unknown) => FilesError) => Promise; /** * Run an operation over many items with bounded concurrency, collecting typed * successes and per-key failures in input order — the generic engine behind * the array form of `upload` / `download` / `head` / `exists`. No provider * exposes a native batch primitive for those, so every adapter fans out here. * * Mirrors {@link deleteManyWithFallback}: `stopOnError` runs sequentially and * returns at the first failure; otherwise a worker pool of `concurrency` * (default 8) drains the list, recording each outcome at its input index so * the returned `results` and `errors` stay in the order the caller supplied. * A separate `success` flag guards against an `Out` value that is itself * falsy. */ export declare const mapMany: (items: Item[], keyOf: (item: Item) => string, run: (item: Item) => Promise, opts?: BulkOptions, mapError?: (error: unknown) => FilesError) => Promise<{ results: Out[]; errors: BulkError[]; }>; //# sourceMappingURL=core.d.ts.map