import type { Files } from "../index.js"; import type { Authorize } from "../internal/files-router/authorize.js"; import type { FilesOperation } from "../internal/files-router/protocol.js"; import type { CompletionStore, OnUploadComplete } from "../internal/files-router/upload-complete.js"; import type { AllowedOrigins } from "../internal/router-core/origin.js"; export type { Authorize, AuthorizeContext, AuthorizeResult, Scope, } from "../internal/files-router/authorize.js"; export type { FilesOperation, InferUploadData, } from "../internal/files-router/protocol.js"; export type { CompletionRecord, CompletionStore, OnUploadComplete, UploadCompleteContext, UploadedFileInfo, UploadVia, } from "../internal/files-router/upload-complete.js"; export { UploadRejectedError } from "../internal/files-router/upload-complete.js"; export type { AllowedOrigins } from "../internal/router-core/origin.js"; export interface CreateFilesRouterOptions { /** A `Files` instance, or a per-request factory (multi-tenant). Pass `files.readonly()` to hard-deny writes. */ files: Files | ((req: Request) => Files | Promise); /** Per-operation gate. Deny-by-default when omitted (only `capabilities` answers). */ authorize?: Authorize; /** * Runs once per verified upload: in `complete` for keyless uploads (after * the landed object's size is checked), and after a keyed `upload(key, * body)` stores its body. Record the upload here; the resolved value is * JSON-serialized back to the client as the upload result's `data`. Throw * to reject the upload — the object is deleted (see `onRejected`) and the * client gets the error; throw `UploadRejectedError` for a 422 with your * message. * * A client that never calls `complete` (a closed tab) never fires it; use * `files-sdk/events` provider notifications to reconcile those. */ onUploadComplete?: OnUploadComplete; /** * What happens to an object whose upload is rejected — by * `onUploadComplete` throwing, or by the complete-time `maxUploadSize` * check. Default `"delete"`. */ onRejected?: "delete" | "keep"; /** * Makes keyless completions single-use: a replayed `complete` gets the * recorded result instead of firing `onUploadComplete` again, and the proxy * PUT refuses (409) further bytes for an upload that already completed. * Upload tokens are stateless, so without a store a client can re-`complete` * an upload, and re-PUT through the proxy, until its token expires — dedupe * on `uploadId` in the hook either way. */ completions?: CompletionStore; /** * Seconds after an upload token expires during which `complete` still * redeems it. The token's expiry bounds when the bytes may start landing; a * large body can finish after it, and the client only completes once it has. * Default 3600. */ completeGracePeriod?: number; /** * Called with every failure whose detail the client doesn't get to see, so * it still reaches your logs: anything thrown that isn't a `FilesError` or * `RouterError` (from your `authorize`/`onUploadComplete` hooks or the * gateway itself; the client gets a generic 500), and a storage * `Provider`/`Unauthorized` error, whose provider message (a filesystem * path, an internal hostname) the client hears only as a fixed one. * Default: `console.error`. */ onError?: (error: unknown, req: Request) => void; /** Declarative allow-list: operations permitted without a hook. A hard gate that runs before `authorize`. */ operations?: readonly FilesOperation[]; /** CSRF/origin allowlist for state-changing actions. Defaults to same-origin when omitted. */ allowedOrigins?: AllowedOrigins; /** * Expiry, in seconds, for `url()`/`download` redirects and upload presigns when * the client doesn't ask for one. Default 300. Not a ceiling — a client may * request a longer `expiresIn`; cap it with `authorize`'s `maxExpiresIn` * (every value is also clamped to the adapter's signing limit). */ defaultExpiresIn?: number; /** Force `Content-Disposition: attachment` on the proxy-download path unless `authorize` opts inline. Default true. */ forceDownloadDisposition?: boolean; /** Cap on a `list` page (and on the page size a `search` walks with). Default 1000. */ maxListLimit?: number; /** Cap on `search` results returned in one page. Default 1000. */ maxSearchResults?: number; /** * Most keys one `search` request reads, matching or not, before it stops * and answers `truncated: true` — so a pattern that matches nothing can't * walk the whole bucket in one request. Default 10000. */ maxSearchScan?: number; /** Reject uploads larger than this (bytes) — bound into the presigned policy + verified on complete. */ maxUploadSize?: number; /** Cap on the `keys[]`/`files[]`/`completions[]` of one bulk request; larger ones get 413 (reason `count`). Default 1000. */ maxBatchSize?: number; /** Ceiling on the `concurrency` a client requests for a bulk op. Default 16. */ maxConcurrency?: number; /** Cap on a JSON (POST) request body, bytes; larger ones get 413. Default 1 MiB. */ maxJsonBodySize?: number; /** Longest accepted `search` pattern, characters. Default 256 (422 beyond it). */ maxSearchPatternLength?: number; /** * Most unbounded wildcards/quantifiers (`*`, `**`, `+`, `{n,}`; an unanchored * regex counts one extra) a `search` pattern may carry. Each one multiplies * the backtracking work per key, so this bounds a client-supplied pattern's * CPU cost. Nested repetition (`(a+)+`) is always refused. Default 4. */ maxSearchWildcards?: number; /** `download` strategy. Default `"auto"` (redirect when the adapter can sign, else proxy). */ downloadMode?: "auto" | "redirect" | "proxy"; /** A `Range` request on a non-range adapter. Default `"reject"` (416). */ onUnsupportedRange?: "reject" | "ignore"; /** HMAC secret for the upload round-trip tokens. Falls back to `FILES_API_SECRET`, then a per-process random (warns). */ secret?: string; /** Clock injection point for token expiry; defaults to `Date.now`. */ now?: () => number; } export interface FilesApi { /** The framework-agnostic core every binding calls. */ handle: (req: Request) => Promise; /** * Type-only: what `onUploadComplete` resolves to. Never set at runtime — * read it with {@link InferUploadData}. */ readonly "~uploadData"?: TData; } export declare const createFilesRouter: (opts: CreateFilesRouterOptions) => FilesApi; //# sourceMappingURL=index.d.ts.map