import type { FilesPlugin } from "../index.js"; import { FilesError } from "../internal/errors.js"; /** * A key-naming rule for {@link validation}. Either a {@link RegExp} the key must * match (anchor it yourself, e.g. `/^[\w.-]+$/`; don't use the `g` flag) or a * predicate that returns `true` for keys you allow. */ export type KeyRule = RegExp | ((key: string) => boolean); /** * Which rule a {@link ValidationError} failed: the `key` naming rule, the * `size` bounds (`maxSize` / `minSize` — the message says which), or the * `allowedTypes` list (`type`). */ export type ValidationReason = "key" | "size" | "type"; /** * Thrown by {@link validation} when a write fails one of its rules. A regular * {@link FilesError} (`code: "Provider"`) with a {@link ValidationReason} * discriminant, so callers can branch on *which* rule failed without parsing * the message: * * ```ts * try { * await files.upload(key, body); * } catch (e) { * if (e instanceof ValidationError && e.reason === "type") { * // reject with "unsupported file type" * } * } * ``` * * Note the `signedUploadUrl()` fail-closed throw is **not** a * `ValidationError` — that's the plugin refusing an unenforceable operation, * not the file failing a rule. */ export declare class ValidationError extends FilesError { readonly reason: ValidationReason; constructor(reason: ValidationReason, message: string); } export interface ValidationOptions { /** Reject uploads larger than this many bytes. */ maxSize?: number; /** Reject uploads smaller than this many bytes — e.g. `1` to refuse empties. */ minSize?: number; /** * Allowed MIME types. Each entry is an exact type (`"image/png"`) or a group * wildcard (`"image/*"`). Matching is case-insensitive and ignores any * `; charset=…` parameter. The type checked is `options.contentType` when you * pass it, else a `Blob`/`File`'s own `.type`, else the type inferred from the * key's extension. */ allowedTypes?: string[]; /** * Constrain the key — a {@link RegExp} it must match, or a predicate that * returns `true` for allowed keys. Enforced on `upload` and on the * destination of `copy` / `move`. */ key?: KeyRule; } /** * A fail-closed guard that vets writes **before they happen** — a max/min size, * an allowed-MIME-type list, and a key-naming rule. It rejects a bad `upload` * (and a `copy` / `move` to a disallowed key) by throwing a * {@link ValidationError} — its `reason` says which rule failed — so no bytes * ever reach the adapter. * * Unlike `compression()` / `encryption()`, it never transforms the body or * writes metadata, so **reads, `url()`, `copy`, and `move` pass straight * through** — there's nothing to undo. The size check is the one exception that * has to see the bytes: for an unknown-length stream it buffers the body to * measure it (the same trade-off the buffering plugins make), so reach for it * before streaming-only setups. Key and type rules never touch the body. * * Place it **first** in the array so it vets the caller's original key and bytes * before anything downstream transforms them: * `plugins: [validation({ maxSize }), compression(), encryption(key)]`. * * `signedUploadUrl()` hands upload capability to a client that writes directly, * bypassing the plugin — so when a size or type rule is set it **fails closed** * (a key-only policy still mints the URL, after checking the key). * * @param options `maxSize`, `minSize`, `allowedTypes`, and/or `key` — any * combination; with none set the plugin is a no-op pass-through. * @example * ```ts * import { createFiles } from "files-sdk"; * import { s3 } from "files-sdk/s3"; * import { validation } from "files-sdk/validation"; * * const files = createFiles({ * adapter: s3({ bucket: "uploads" }), * plugins: [ * validation({ * maxSize: 10 * 1024 * 1024, // 10 MiB * allowedTypes: ["image/*", "application/pdf"], * key: /^[\w.-]+$/, * }), * ], * }); * * await files.upload("photo.png", bytes); // ok * await files.upload("notes.txt", "…"); // throws: type not allowed * ``` */ export declare const validation: (options?: ValidationOptions) => FilesPlugin; //# sourceMappingURL=index.d.ts.map