import type { StandardSchemaV1 } from "@standard-schema/spec";
import type { StorageMetadata, StorageObject, StoragePort } from "../ports/index.js";
import type { ProviderInstrumentationTarget } from "../providers/index.js";
/**
 * Any Standard Schema compatible validator.
 */
export type StandardSchema = StandardSchemaV1<unknown, unknown>;
/**
 * Value or promise of that value.
 */
export type MaybePromise<T> = T | Promise<T>;
/**
 * Infer the parsed output type from a Standard Schema.
 */
export type InferSchemaOutput<T extends StandardSchemaV1> = StandardSchemaV1.InferOutput<T>;
/**
 * File metadata declared by a browser before an upload starts.
 */
export interface UploadFileIntent {
    /**
     * Original file name supplied by the client.
     */
    name: string;
    /**
     * MIME content type supplied by the client.
     */
    contentType: string;
    /**
     * File size in bytes.
     */
    size: number;
    /**
     * Optional expected checksum for this file. Direct uploads use this to
     * verify the object bytes during completion.
     */
    checksum?: UploadFileChecksum;
}
/**
 * Checksum algorithms supported by Beignet upload verification.
 */
export type UploadChecksumAlgorithm = "sha256";
/**
 * Expected or computed file checksum.
 */
export interface UploadFileChecksum {
    /**
     * Hash algorithm used for the checksum.
     */
    algorithm: UploadChecksumAlgorithm;
    /**
     * Lowercase hex digest.
     */
    value: string;
}
/**
 * Checksum verification requested by an upload definition.
 */
export interface UploadChecksumRequirement {
    /**
     * Hash algorithm to compute.
     */
    algorithm: UploadChecksumAlgorithm;
    /**
     * Whether direct upload preparation/completion must include a checksum.
     *
     * @default true
     */
    required?: boolean;
}
/**
 * Constraints for files accepted by an upload definition.
 */
export interface UploadFileConstraints {
    /**
     * Accepted MIME content types. Omit to accept any content type.
     */
    contentTypes?: readonly string[];
    /**
     * Maximum accepted file size in bytes.
     */
    maxSizeBytes?: number;
    /**
     * Maximum files accepted by one request.
     *
     * @default 1
     */
    maxFiles?: number;
    /**
     * Object visibility written to storage.
     *
     * @default "private"
     */
    visibility?: "private" | "public";
    /**
     * Cache-Control value written to storage.
     */
    cacheControl?: string;
    /**
     * Verify supported MIME types against file signatures instead of trusting
     * only the client-declared content type.
     *
     * @default "signature"
     */
    contentTypeVerification?: "signature" | false;
    /**
     * Request checksum verification for direct uploads and expose the requirement
     * through the upload manifest so browser clients can send expected digests.
     */
    checksum?: UploadChecksumRequirement;
}
/**
 * Parsed file intent with a generated upload id and storage key.
 */
export interface PreparedUploadFile extends UploadFileIntent {
    /**
     * Stable upload id used to correlate prepare, direct upload, and complete.
     */
    uploadId: string;
    /**
     * Storage key that should receive the file.
     */
    key: string;
}
/**
 * Direct upload instruction returned by an upload signer.
 */
export interface DirectUploadInstruction {
    method: "PUT";
    url: string;
    headers?: Record<string, string>;
    expiresAt: string;
}
/**
 * Arguments passed to an upload signer.
 */
export interface SignUploadArgs {
    uploadName: string;
    uploadId: string;
    key: string;
    file: UploadFileIntent;
    metadata: unknown;
    storage: {
        visibility: "private" | "public";
        cacheControl?: string;
        metadata: StorageMetadata;
    };
}
/**
 * Port for providers that can create direct-upload instructions.
 */
export interface UploadSignerPort {
    /**
     * Create direct upload instructions for one prepared file.
     */
    sign(args: SignUploadArgs): MaybePromise<DirectUploadInstruction>;
}
/**
 * Prepared upload file returned to clients.
 */
export interface PreparedUploadResultFile extends PreparedUploadFile {
    /**
     * Direct upload instruction when a signer is configured.
     */
    direct?: DirectUploadInstruction;
}
/**
 * Result returned by `prepare(...)`.
 */
export interface PrepareUploadResult {
    uploadName: string;
    mode: "direct" | "server";
    files: PreparedUploadResultFile[];
}
/**
 * File object completed by direct upload or server upload.
 */
export interface CompletedUploadFile extends PreparedUploadFile {
    object: StorageObject;
}
/**
 * Result returned by upload completion.
 */
export interface CompleteUploadResult<Result = unknown> {
    uploadName: string;
    files: CompletedUploadFile[];
    result: Result;
}
/**
 * Input for `prepare(...)`.
 */
export interface PrepareUploadInput {
    metadata: unknown;
    files: readonly UploadFileIntent[];
}
/**
 * Input for `complete(...)`.
 */
export interface CompleteUploadInput {
    metadata: unknown;
    files: readonly PreparedUploadFile[];
}
/**
 * Input for server-handled multipart uploads.
 */
export interface ServerUploadInput {
    formData: FormData;
}
/**
 * Authorization result accepted by upload definitions.
 */
export type UploadAuthorizeResult = boolean | undefined | {
    allowed: boolean;
    reason?: string;
};
/**
 * Upload access mode.
 *
 * Protected uploads require an `authorize(...)` hook. Public uploads are
 * intentionally reachable without that hook.
 */
export type UploadAccess = "protected" | "public";
/**
 * Arguments passed to upload definition hooks.
 */
export interface UploadHookArgs<Metadata, Ctx> {
    ctx: Ctx;
    metadata: Metadata;
}
/**
 * Arguments passed to file-specific upload hooks.
 */
export interface UploadFileHookArgs<Metadata, Ctx> extends UploadHookArgs<Metadata, Ctx> {
    file: UploadFileIntent;
    uploadId: string;
}
/**
 * Arguments passed to `onComplete(...)`.
 */
export interface UploadCompleteHookArgs<Metadata, Ctx> extends UploadHookArgs<Metadata, Ctx> {
    files: CompletedUploadFile[];
}
/**
 * Arguments passed to `verifyFile(...)` after a file exists in storage and
 * before `onComplete(...)` runs.
 */
export interface UploadVerifyFileHookArgs<Metadata, Ctx> extends UploadHookArgs<Metadata, Ctx> {
    file: CompletedUploadFile;
    storage: StoragePort;
}
/**
 * Verification result accepted by `verifyFile(...)`.
 */
export type UploadFileVerificationResult = boolean | undefined | {
    valid: boolean;
    reason?: string;
    details?: unknown;
};
/**
 * Upload definition options.
 */
export interface DefineUploadOptions<MetadataSchema extends StandardSchema, Ctx, Result> {
    /**
     * Metadata schema submitted with prepare, server upload, and complete calls.
     */
    metadata: MetadataSchema;
    /**
     * File constraints for this upload workflow.
     */
    file: UploadFileConstraints;
    /**
     * Whether this upload may be prepared without an authorize hook.
     *
     * @default "protected"
     */
    access?: UploadAccess;
    /**
     * Optional human-readable description for docs and tooling.
     */
    description?: string;
    /**
     * Check whether the current actor may start this upload.
     */
    authorize?(args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<UploadAuthorizeResult>;
    /**
     * Build the storage key for one file.
     */
    key(args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<string>;
    /**
     * Add storage metadata for one file.
     */
    storageMetadata?(args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<StorageMetadata>;
    /**
     * Run after a file exists in storage and before `onComplete(...)`. Use this
     * for app-owned scanning, moderation, or quarantine decisions.
     */
    verifyFile?(args: UploadVerifyFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<UploadFileVerificationResult>;
    /**
     * Run after files exist in storage.
     */
    onComplete?(args: UploadCompleteHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<Result>;
}
/**
 * Upload definition created by `defineUpload(...)`.
 */
export interface UploadDef<Name extends string = string, MetadataSchema extends StandardSchema = StandardSchema, Ctx = unknown, Result = unknown> {
    readonly kind: "upload";
    readonly name: Name;
    readonly metadata: MetadataSchema;
    readonly file: UploadFileConstraints;
    readonly access?: UploadAccess;
    readonly description?: string;
    authorize?(args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<UploadAuthorizeResult>;
    key(args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<string>;
    storageMetadata?(args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<StorageMetadata>;
    verifyFile?(args: UploadVerifyFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<UploadFileVerificationResult>;
    onComplete?(args: UploadCompleteHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>): MaybePromise<Result>;
}
/**
 * Infer the parsed metadata type for an upload definition.
 */
export type InferUploadMetadata<U extends UploadDef> = U["metadata"] extends StandardSchemaV1<unknown, infer Output> ? Output : never;
/**
 * Infer the result returned by an upload definition's completion hook.
 */
export type InferUploadResult<U extends UploadDef> = U extends UploadDef<string, StandardSchema, unknown, infer Result> ? Result : unknown;
/**
 * Nested upload registry shape used by server registration and typed clients.
 */
export interface UploadRegistry {
    /**
     * Upload definition or nested upload registry.
     */
    readonly [key: string]: UploadDef | UploadRegistry;
}
/**
 * Infer every upload definition contained in a nested upload registry.
 */
export type UploadFromRegistry<Registry> = Registry extends UploadDef ? Registry : Registry extends readonly (infer Upload)[] ? Upload extends UploadDef ? Upload : never : Registry extends object ? {
    [Key in keyof Registry]: UploadFromRegistry<Registry[Key]>;
}[keyof Registry] : never;
/**
 * Client-safe upload metadata generated from server upload definitions.
 */
export interface UploadManifestEntry {
    /**
     * Upload route name.
     */
    name: string;
    /**
     * Optional human-readable upload description.
     */
    description?: string;
    /**
     * File constraints safe to expose to browser UI code.
     */
    file: UploadFileConstraints;
}
/**
 * Request body limits for upload route actions.
 */
export interface UploadRequestLimits {
    /**
     * Maximum JSON body size for prepare and complete actions.
     *
     * @default 262144
     */
    jsonMaxBytes?: number;
    /**
     * Maximum multipart body size for server-handled upload actions when
     * Content-Length is present. File constraints still enforce per-file limits.
     *
     * @default 26214400
     */
    multipartMaxBytes?: number;
}
/**
 * Options for `createUploadRouter(...)`.
 */
export interface CreateUploadRouterOptions<Ctx> {
    /**
     * Upload definitions registered with this router.
     */
    uploads: readonly UploadDef<string, StandardSchema, Ctx, unknown>[];
    /**
     * Request context value or lazy context factory.
     */
    ctx: Ctx | (() => MaybePromise<Ctx>);
    /**
     * Storage port used for server uploads and direct upload completion checks.
     */
    storage: StoragePort;
    /**
     * Optional signer used to prepare direct upload instructions.
     */
    signer?: UploadSignerPort;
    /**
     * Request body limits for upload actions.
     */
    limits?: UploadRequestLimits;
    /**
     * Optional instrumentation target used by devtools/provider watchers.
     */
    instrumentation?: ProviderInstrumentationTarget;
    /**
     * Optional upload id generator for tests or custom id policies.
     */
    id?: () => string;
}
/**
 * Framework-neutral upload router.
 */
export interface UploadRouter {
    prepare(uploadName: string, input: PrepareUploadInput): Promise<PrepareUploadResult>;
    complete(uploadName: string, input: CompleteUploadInput): Promise<CompleteUploadResult>;
    upload(uploadName: string, input: ServerUploadInput): Promise<CompleteUploadResult>;
    handleRequest(request: Request, options: {
        uploadName: string;
        action: "prepare" | "complete" | "upload";
    }): Promise<Response>;
}
/**
 * Machine-readable upload error codes.
 */
export type UploadErrorCode = "UPLOAD_NOT_FOUND" | "INVALID_UPLOAD_ACTION" | "INVALID_UPLOAD_METADATA" | "INVALID_UPLOAD_FILE" | "UNAUTHORIZED_UPLOAD" | "UPLOAD_OBJECT_NOT_FOUND" | "UPLOAD_BODY_TOO_LARGE" | "INVALID_UPLOAD_BODY";
/**
 * Base error for expected upload failures.
 *
 * Upload workflows throw one of the specific subclasses, such as
 * {@link UploadNotFoundError} or {@link UnauthorizedUploadError}. Catch this
 * base class to handle any expected upload failure; the upload router maps it
 * to an HTTP response using `code`, `status`, and `details`.
 */
export declare class UploadError extends Error {
    readonly code: UploadErrorCode;
    readonly status: number;
    readonly details?: unknown;
    protected constructor(args: {
        code: UploadErrorCode;
        message: string;
        status?: number;
        details?: unknown;
    });
}
/**
 * Error thrown when an upload name is not registered on the router.
 */
export declare class UploadNotFoundError extends UploadError {
    readonly code: "UPLOAD_NOT_FOUND";
    constructor(args: {
        message: string;
        details?: unknown;
    });
}
/**
 * Error thrown when an upload request targets an unknown upload action.
 */
export declare class InvalidUploadActionError extends UploadError {
    readonly code: "INVALID_UPLOAD_ACTION";
    constructor(args: {
        message: string;
        details?: unknown;
    });
}
/**
 * Error thrown when upload metadata fails schema validation.
 */
export declare class InvalidUploadMetadataError extends UploadError {
    readonly code: "INVALID_UPLOAD_METADATA";
    constructor(args: {
        message: string;
        details?: unknown;
    });
}
/**
 * Error thrown when a file fails upload validation, such as file count,
 * content type (415), size limits (413), or prepared-file mismatches.
 */
export declare class InvalidUploadFileError extends UploadError {
    readonly code: "INVALID_UPLOAD_FILE";
    constructor(args: {
        message: string;
        details?: unknown;
        status?: number;
    });
}
/**
 * Error thrown when an upload is denied by authorize(...) or lacks
 * authorization configuration.
 */
export declare class UnauthorizedUploadError extends UploadError {
    readonly code: "UNAUTHORIZED_UPLOAD";
    constructor(args: {
        message: string;
        details?: unknown;
    });
}
/**
 * Error thrown when a completed upload references a stored object that does
 * not exist.
 */
export declare class UploadObjectNotFoundError extends UploadError {
    readonly code: "UPLOAD_OBJECT_NOT_FOUND";
    constructor(args: {
        message: string;
        details?: unknown;
    });
}
/**
 * Error thrown when an upload request body exceeds the configured size limit.
 */
export declare class UploadBodyTooLargeError extends UploadError {
    readonly code: "UPLOAD_BODY_TOO_LARGE";
    constructor(args: {
        message: string;
        details?: unknown;
    });
}
/**
 * Error thrown when an upload request body cannot be parsed or has an
 * invalid shape.
 */
export declare class InvalidUploadBodyError extends UploadError {
    readonly code: "INVALID_UPLOAD_BODY";
    constructor(args: {
        message: string;
        details?: unknown;
    });
}
/**
 * Define a typed upload workflow.
 */
export declare function defineUpload<const Name extends string, MetadataSchema extends StandardSchema, Ctx = unknown, Result = unknown>(name: Name, options: DefineUploadOptions<MetadataSchema, Ctx, Result>): UploadDef<Name, MetadataSchema, Ctx, Result>;
/**
 * Context-bound upload helper factory.
 */
export interface Uploads<Ctx> {
    /**
     * Define an upload workflow with the bound context type.
     */
    defineUpload<const Name extends string, MetadataSchema extends StandardSchema, Result = unknown>(name: Name, options: DefineUploadOptions<MetadataSchema, Ctx, Result>): UploadDef<Name, MetadataSchema, Ctx, Result>;
}
/**
 * Create upload helper methods bound to an application context type.
 *
 * Call it once in `lib/uploads.ts`:
 *
 * ```ts
 * export const { defineUpload } = createUploads<AppContext>();
 * ```
 */
export declare function createUploads<Ctx>(): Uploads<Ctx>;
/**
 * Define a nested upload registry while preserving upload names and metadata
 * types for client code.
 */
export declare function defineUploads<const Uploads extends UploadRegistry>(uploads: Uploads): Uploads;
/**
 * Flatten a nested upload registry into the list expected by
 * `createUploadRouter(...)`.
 */
export declare function uploadsFromRegistry(uploads: UploadRegistry | readonly UploadDef[]): UploadDef[];
/**
 * Create client-safe upload metadata for browser helpers.
 */
export declare function createUploadManifest(uploads: UploadRegistry | readonly UploadDef[]): UploadManifestEntry[];
/**
 * Create deterministic direct upload instructions for tests.
 */
export declare function createMemoryUploadSigner(options?: {
    baseUrl?: string;
    expiresAt?: string;
}): UploadSignerPort;
/**
 * Create a framework-neutral upload router.
 */
export declare function createUploadRouter<Ctx>(options: CreateUploadRouterOptions<Ctx>): UploadRouter;
//# sourceMappingURL=index.d.ts.map