import { AwsClient } from "aws4fetch";

//#region src/core/providers/providers.d.ts

/**
 * @fileoverview Cloud Storage Providers System
 *
 * This module provides a comprehensive system for configuring different cloud storage providers
 * with environment-based configuration, type-safe initialization, and automatic endpoint resolution.
 *
 * The provider system supports multiple tiers of cloud storage services:
 * - **Tier 1**: Fully supported with comprehensive testing (AWS S3, Cloudflare R2, DigitalOcean Spaces, MinIO)
 * - **Tier 2**: Enterprise/Hyperscale providers (Azure Blob, IBM Cloud, Oracle OCI)
 * - **Tier 3**: Cost-optimized providers (Wasabi, Backblaze B2, Storj DCS)
 * - **Tier 4**: Performance/Specialized providers (Telnyx, Tigris, Cloudian)
 *
 * Features:
 * - Environment variable auto-detection with fallbacks
 * - Type-safe configuration with TypeScript inference
 * - Automatic endpoint generation for known providers
 * - Validation and error reporting
 * - Custom domain and ACL support
 *
 * @example Basic AWS S3 Configuration
 * ```typescript
 * import { createProvider } from 'pushduck/server';
 *
 * const s3Config = createProvider('aws', {
 *   bucket: 'my-uploads',
 *   region: 'us-east-1',
 *   // Credentials auto-loaded from AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
 * });
 * ```
 *
 * @example Cloudflare R2 Configuration
 * ```typescript
 * const r2Config = createProvider('cloudflareR2', {
 *   bucket: 'my-r2-bucket',
 *   accountId: 'your-account-id',
 *   // Credentials from CLOUDFLARE_R2_ACCESS_KEY_ID, CLOUDFLARE_R2_SECRET_ACCESS_KEY
 * });
 * ```
 *
 * @example MinIO Self-hosted Configuration
 * ```typescript
 * const minioConfig = createProvider('minio', {
 *   endpoint: 'http://localhost:9000',
 *   bucket: 'uploads',
 *   accessKeyId: 'minioadmin',
 *   secretAccessKey: 'minioadmin',
 *   useSSL: false,
 * });
 * ```
 *
 * @example Environment Variable Setup
 * ```bash
 * # AWS S3
 * export AWS_ACCESS_KEY_ID="your-access-key"
 * export AWS_SECRET_ACCESS_KEY="your-secret-key"
 * export AWS_REGION="us-east-1"
 *
 * # Cloudflare R2
 * export CLOUDFLARE_R2_ACCESS_KEY_ID="your-r2-access-key"
 * export CLOUDFLARE_R2_SECRET_ACCESS_KEY="your-r2-secret-key"
 * export CLOUDFLARE_ACCOUNT_ID="your-account-id"
 *
 * # DigitalOcean Spaces
 * export DO_SPACES_ACCESS_KEY_ID="your-spaces-key"
 * export DO_SPACES_SECRET_ACCESS_KEY="your-spaces-secret"
 * export DO_SPACES_REGION="nyc3"
 * ```
 *
 */
/**
 * Base configuration interface for all cloud storage providers.
 * Contains common properties shared across all provider implementations.
 *
 * @interface BaseProviderConfig
 */
interface BaseProviderConfig {
  /** Provider identifier string */
  provider: string;
  /** Geographic region for the storage service */
  region?: string;
  /** Name of the storage bucket/container */
  bucket: string;
  /** Access Control List permissions (e.g., 'public-read', 'private') */
  acl?: string;
  /** Custom domain for file URLs (e.g., 'cdn.example.com') */
  customDomain?: string;
  /** Force path-style URLs instead of virtual-hosted style */
  forcePathStyle?: boolean;
}
/**
 * Configuration for Amazon Web Services S3.
 * The most widely used object storage service with global availability.
 *
 * @interface AWSProviderConfig
 * @extends BaseProviderConfig
 *
 * @example Basic Configuration
 * ```typescript
 * const awsConfig: AWSProviderConfig = {
 *   provider: 'aws',
 *   bucket: 'my-app-uploads',
 *   region: 'us-east-1',
 *   accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
 *   secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
 * };
 * ```
 *
 * @example With Custom Domain
 * ```typescript
 * const awsWithCDN: AWSProviderConfig = {
 *   provider: 'aws',
 *   bucket: 'my-uploads',
 *   region: 'us-east-1',
 *   accessKeyId: 'AKIA...',
 *   secretAccessKey: 'secret...',
 *   customDomain: 'cdn.myapp.com',
 *   acl: 'public-read',
 * };
 * ```
 */
interface AWSProviderConfig extends BaseProviderConfig {
  provider: "aws";
  /** AWS Access Key ID */
  accessKeyId: string;
  /** AWS Secret Access Key */
  secretAccessKey: string;
  /** AWS region (required) */
  region: string;
  /** AWS Session Token for temporary credentials */
  sessionToken?: string;
}
/**
 * Configuration for Cloudflare R2 object storage.
 * S3-compatible storage with zero egress fees and global distribution.
 *
 * @interface CloudflareR2Config
 * @extends BaseProviderConfig
 *
 * @example Basic Configuration
 * ```typescript
 * const r2Config: CloudflareR2Config = {
 *   provider: 'cloudflare-r2',
 *   bucket: 'my-r2-bucket',
 *   accountId: 'your-cloudflare-account-id',
 *   accessKeyId: 'your-r2-access-key',
 *   secretAccessKey: 'your-r2-secret-key',
 * };
 * ```
 *
 * @example With Custom Domain
 * ```typescript
 * const r2WithDomain: CloudflareR2Config = {
 *   provider: 'cloudflare-r2',
 *   bucket: 'assets',
 *   accountId: 'abc123',
 *   accessKeyId: 'key123',
 *   secretAccessKey: 'secret123',
 *   customDomain: 'assets.myapp.com',
 * };
 * ```
 */
interface CloudflareR2Config extends BaseProviderConfig {
  provider: "cloudflare-r2";
  /** Cloudflare Account ID */
  accountId: string;
  /** R2 Access Key ID */
  accessKeyId: string;
  /** R2 Secret Access Key */
  secretAccessKey: string;
  /** Region (typically 'auto' for R2) */
  region?: "auto";
  /** Custom endpoint (auto-generated from accountId if not provided) */
  endpoint?: string;
}
/**
 * Configuration for DigitalOcean Spaces object storage.
 * S3-compatible storage service integrated with DigitalOcean's ecosystem.
 *
 * @interface DigitalOceanSpacesConfig
 * @extends BaseProviderConfig
 *
 * @example Basic Configuration
 * ```typescript
 * const spacesConfig: DigitalOceanSpacesConfig = {
 *   provider: 'digitalocean-spaces',
 *   bucket: 'my-space',
 *   region: 'nyc3',
 *   accessKeyId: 'your-spaces-key',
 *   secretAccessKey: 'your-spaces-secret',
 * };
 * ```
 *
 * @example Available Regions
 * ```typescript
 * const regions = ['nyc3', 'ams3', 'sgp1', 'sfo3', 'fra1'];
 * const spacesConfig: DigitalOceanSpacesConfig = {
 *   provider: 'digitalocean-spaces',
 *   bucket: 'global-assets',
 *   region: 'fra1', // Frankfurt
 *   accessKeyId: process.env.DO_SPACES_ACCESS_KEY_ID!,
 *   secretAccessKey: process.env.DO_SPACES_SECRET_ACCESS_KEY!,
 * };
 * ```
 */
interface DigitalOceanSpacesConfig extends BaseProviderConfig {
  provider: "digitalocean-spaces";
  /** Spaces Access Key ID */
  accessKeyId: string;
  /** Spaces Secret Access Key */
  secretAccessKey: string;
  /** DigitalOcean region */
  region: string;
  /** Custom endpoint (auto-generated from region if not provided) */
  endpoint?: string;
}
/**
 * Configuration for MinIO object storage.
 * Self-hosted S3-compatible storage for on-premises or private cloud deployments.
 *
 * @interface MinIOConfig
 * @extends BaseProviderConfig
 *
 * @example Local Development
 * ```typescript
 * const minioConfig: MinIOConfig = {
 *   provider: 'minio',
 *   endpoint: 'http://localhost:9000',
 *   bucket: 'uploads',
 *   accessKeyId: 'minioadmin',
 *   secretAccessKey: 'minioadmin',
 *   useSSL: false,
 * };
 * ```
 *
 * @example Production Setup
 * ```typescript
 * const minioProduction: MinIOConfig = {
 *   provider: 'minio',
 *   endpoint: 'https://minio.mycompany.com',
 *   bucket: 'production-uploads',
 *   accessKeyId: process.env.MINIO_ACCESS_KEY!,
 *   secretAccessKey: process.env.MINIO_SECRET_KEY!,
 *   useSSL: true,
 *   port: 9000,
 * };
 * ```
 */
interface MinIOConfig extends BaseProviderConfig {
  provider: "minio";
  /** MinIO server endpoint URL */
  endpoint: string;
  /** MinIO access key */
  accessKeyId: string;
  /** MinIO secret key */
  secretAccessKey: string;
  /** Whether to use SSL/TLS */
  useSSL?: boolean;
  /** Custom port (default: 9000) */
  port?: number;
}
interface AzureBlobConfig extends BaseProviderConfig {
  provider: "azure-blob";
  accountName: string;
  accessKeyId: string;
  secretAccessKey: string;
  endpoint?: string;
}
interface IBMCloudConfig extends BaseProviderConfig {
  provider: "ibm-cloud";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint: string;
  serviceInstanceId?: string;
}
interface OracleOCIConfig extends BaseProviderConfig {
  provider: "oracle-oci";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint: string;
  namespace?: string;
}
interface WasabiConfig extends BaseProviderConfig {
  provider: "wasabi";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint?: string;
}
interface BackblazeB2Config extends BaseProviderConfig {
  provider: "backblaze-b2";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint: string;
}
interface StorjDCSConfig extends BaseProviderConfig {
  provider: "storj-dcs";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint?: string;
}
interface TelnyxStorageConfig extends BaseProviderConfig {
  provider: "telnyx-storage";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint: string;
}
interface TigrisDataConfig extends BaseProviderConfig {
  provider: "tigris-data";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint: string;
  region?: "auto";
}
interface CloudianHyperStoreConfig extends BaseProviderConfig {
  provider: "cloudian-hyperstore";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint: string;
}
interface GoogleCloudStorageConfig extends BaseProviderConfig {
  provider: "gcs";
  projectId: string;
  keyFilename?: string;
  credentials?: object;
}
interface S3CompatibleConfig extends BaseProviderConfig {
  provider: "s3-compatible";
  accessKeyId: string;
  secretAccessKey: string;
  endpoint: string;
}
type ProviderConfig = AWSProviderConfig | CloudflareR2Config | DigitalOceanSpacesConfig | MinIOConfig | AzureBlobConfig | IBMCloudConfig | OracleOCIConfig | WasabiConfig | BackblazeB2Config | StorjDCSConfig | TelnyxStorageConfig | TigrisDataConfig | CloudianHyperStoreConfig | GoogleCloudStorageConfig | S3CompatibleConfig;
declare const PROVIDER_SPECS: {
  readonly aws: {
    readonly provider: "aws";
    readonly configKeys: {
      readonly region: readonly ["AWS_REGION", "S3_REGION"];
      readonly bucket: readonly ["AWS_S3_BUCKET", "S3_BUCKET", "S3_BUCKET_NAME"];
      readonly accessKeyId: readonly ["AWS_ACCESS_KEY_ID", "S3_ACCESS_KEY_ID"];
      readonly secretAccessKey: readonly ["AWS_SECRET_ACCESS_KEY", "S3_SECRET_ACCESS_KEY"];
      readonly sessionToken: readonly ["AWS_SESSION_TOKEN"];
      readonly acl: readonly ["S3_ACL"];
      readonly customDomain: readonly ["S3_CUSTOM_DOMAIN"];
      readonly forcePathStyle: readonly ["S3_FORCE_PATH_STYLE"];
    };
    readonly defaults: {
      readonly region: "us-east-1";
      readonly acl: "private";
    };
  };
  readonly cloudflareR2: {
    readonly provider: "cloudflare-r2";
    readonly configKeys: {
      readonly accountId: readonly ["CLOUDFLARE_ACCOUNT_ID", "R2_ACCOUNT_ID"];
      readonly bucket: readonly ["CLOUDFLARE_R2_BUCKET", "R2_BUCKET"];
      readonly accessKeyId: readonly ["CLOUDFLARE_R2_ACCESS_KEY_ID", "R2_ACCESS_KEY_ID"];
      readonly secretAccessKey: readonly ["CLOUDFLARE_R2_SECRET_ACCESS_KEY", "R2_SECRET_ACCESS_KEY"];
      readonly endpoint: readonly ["CLOUDFLARE_R2_ENDPOINT", "R2_ENDPOINT"];
      readonly customDomain: readonly ["R2_CUSTOM_DOMAIN"];
      readonly acl: readonly [];
    };
    readonly defaults: {
      readonly region: "auto";
      readonly acl: "private";
    };
    readonly customLogic: (config: any, computed: any) => {
      endpoint: any;
    };
  };
  readonly digitalOceanSpaces: {
    readonly provider: "digitalocean-spaces";
    readonly configKeys: {
      readonly region: readonly ["DO_SPACES_REGION", "DIGITALOCEAN_SPACES_REGION"];
      readonly bucket: readonly ["DO_SPACES_BUCKET", "DIGITALOCEAN_SPACES_BUCKET"];
      readonly accessKeyId: readonly ["DO_SPACES_ACCESS_KEY_ID", "DIGITALOCEAN_SPACES_ACCESS_KEY_ID"];
      readonly secretAccessKey: readonly ["DO_SPACES_SECRET_ACCESS_KEY", "DIGITALOCEAN_SPACES_SECRET_ACCESS_KEY"];
      readonly endpoint: readonly ["DO_SPACES_ENDPOINT", "DIGITALOCEAN_SPACES_ENDPOINT"];
      readonly customDomain: readonly ["DO_SPACES_CUSTOM_DOMAIN"];
      readonly acl: readonly [];
    };
    readonly defaults: {
      readonly region: "nyc3";
      readonly acl: "private";
    };
    readonly customLogic: (config: any, computed: any) => {
      endpoint: any;
    };
  };
  readonly minio: {
    readonly provider: "minio";
    readonly configKeys: {
      readonly endpoint: readonly ["MINIO_ENDPOINT"];
      readonly bucket: readonly ["MINIO_BUCKET"];
      readonly accessKeyId: readonly ["MINIO_ACCESS_KEY_ID", "MINIO_ACCESS_KEY"];
      readonly secretAccessKey: readonly ["MINIO_SECRET_ACCESS_KEY", "MINIO_SECRET_KEY"];
      readonly region: readonly ["MINIO_REGION"];
      readonly customDomain: readonly ["MINIO_CUSTOM_DOMAIN"];
      readonly acl: readonly [];
    };
    readonly defaults: {
      readonly endpoint: "localhost:9000";
      readonly region: "us-east-1";
      readonly acl: "private";
    };
    readonly customLogic: (config: any, computed: any) => {
      useSSL: any;
      port: number | undefined;
    };
  };
  readonly gcs: {
    readonly provider: "gcs";
    readonly configKeys: {
      readonly projectId: readonly ["GOOGLE_CLOUD_PROJECT_ID", "GCS_PROJECT_ID"];
      readonly bucket: readonly ["GCS_BUCKET", "GOOGLE_CLOUD_STORAGE_BUCKET"];
      readonly keyFilename: readonly ["GOOGLE_APPLICATION_CREDENTIALS", "GCS_KEY_FILE"];
      readonly region: readonly ["GCS_REGION"];
      readonly customDomain: readonly ["GCS_CUSTOM_DOMAIN"];
      readonly acl: readonly [];
    };
    readonly defaults: {
      readonly region: "us-central1";
      readonly acl: "private";
    };
    readonly customLogic: (config: any) => {
      credentials: any;
    };
  };
  readonly s3Compatible: {
    readonly provider: "s3-compatible";
    readonly configKeys: {
      readonly endpoint: readonly ["S3_ENDPOINT", "S3_COMPATIBLE_ENDPOINT"];
      readonly bucket: readonly ["S3_BUCKET", "S3_BUCKET_NAME"];
      readonly accessKeyId: readonly ["S3_ACCESS_KEY_ID", "ACCESS_KEY_ID"];
      readonly secretAccessKey: readonly ["S3_SECRET_ACCESS_KEY", "SECRET_ACCESS_KEY"];
      readonly region: readonly ["S3_REGION", "REGION"];
      readonly customDomain: readonly ["S3_CUSTOM_DOMAIN"];
      readonly acl: readonly ["S3_ACL"];
    };
    readonly defaults: {
      readonly region: "us-east-1";
      readonly acl: "private";
      readonly forcePathStyle: true;
    };
  };
};
type ProviderSpecsType = typeof PROVIDER_SPECS;
type ProviderType = keyof ProviderSpecsType;
/**
 * Maps each provider type to its corresponding configuration interface
 * This enables type-safe provider configuration in createUploadConfig().provider()
 */
type ProviderConfigMap = {
  aws: Partial<Omit<AWSProviderConfig, "provider">>;
  cloudflareR2: Partial<Omit<CloudflareR2Config, "provider">>;
  digitalOceanSpaces: Partial<Omit<DigitalOceanSpacesConfig, "provider">>;
  minio: Partial<Omit<MinIOConfig, "provider">>;
  gcs: Partial<Omit<GoogleCloudStorageConfig, "provider">>;
  s3Compatible: Partial<Omit<S3CompatibleConfig, "provider">>;
};
/**
 * Type-safe provider configuration function
 * Usage: createProvider("aws", { bucket: "my-bucket", region: "us-west-2" })
 */
/**
 * Creates a provider configuration with automatic environment variable detection.
 * This is the main factory function for creating type-safe provider configurations
 * with automatic credential loading from environment variables.
 *
 * @template T - The provider type
 * @param type - The provider type identifier
 * @param config - Partial configuration object (missing values loaded from env)
 * @returns Complete provider configuration
 *
 * @example AWS S3 Provider
 * ```typescript
 * // Environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
 * const s3Config = createProvider('aws', {
 *   bucket: 'my-uploads',
 *   // region, accessKeyId, secretAccessKey auto-loaded from env
 * });
 * ```
 *
 * @example Cloudflare R2 Provider
 * ```typescript
 * // Environment variables: CLOUDFLARE_R2_ACCESS_KEY_ID, CLOUDFLARE_R2_SECRET_ACCESS_KEY, CLOUDFLARE_ACCOUNT_ID
 * const r2Config = createProvider('cloudflareR2', {
 *   bucket: 'my-r2-bucket',
 *   // accountId, accessKeyId, secretAccessKey auto-loaded from env
 * });
 * ```
 *
 * @example MinIO Provider
 * ```typescript
 * const minioConfig = createProvider('minio', {
 *   endpoint: 'http://localhost:9000',
 *   bucket: 'uploads',
 *   accessKeyId: 'minioadmin',
 *   secretAccessKey: 'minioadmin',
 *   useSSL: false,
 * });
 * ```
 *
 * @example DigitalOcean Spaces
 * ```typescript
 * // Environment variables: DO_SPACES_ACCESS_KEY_ID, DO_SPACES_SECRET_ACCESS_KEY, DO_SPACES_REGION
 * const spacesConfig = createProvider('digitalOceanSpaces', {
 *   bucket: 'my-space',
 *   // region, accessKeyId, secretAccessKey auto-loaded from env
 * });
 * ```
 *
 * @throws {Error} When required configuration is missing and not available in environment
 */
declare function createProvider<T extends ProviderType>(type: T, config?: ProviderConfigMap[T]): ProviderConfig;
/**
 * Validates a provider configuration and returns detailed error information.
 * This function checks for required fields, validates endpoints, and ensures
 * the configuration is complete and correct.
 *
 * @param config - The provider configuration to validate
 * @returns Validation result with success status and error details
 *
 * @example Validating AWS Configuration
 * ```typescript
 * const awsConfig = createProvider('aws', {
 *   bucket: 'my-uploads',
 *   region: 'us-east-1',
 *   accessKeyId: 'AKIA...',
 *   secretAccessKey: 'secret...',
 * });
 *
 * const validation = validateProviderConfig(awsConfig);
 * if (!validation.valid) {
 *   console.error('Configuration errors:', validation.errors);
 *   // ["Missing required field: accessKeyId", "Invalid region format"]
 * }
 * ```
 *
 * @example Handling Validation Errors
 * ```typescript
 * const config = createProvider('cloudflareR2', {
 *   bucket: 'test-bucket',
 *   // Missing accountId, accessKeyId, secretAccessKey
 * });
 *
 * const { valid, errors } = validateProviderConfig(config);
 * if (!valid) {
 *   throw new Error(`Provider configuration invalid: ${errors.join(', ')}`);
 * }
 * ```
 *
 * @example Validation in Setup
 * ```typescript
 * function setupStorage(providerConfig: ProviderConfig) {
 *   const validation = validateProviderConfig(providerConfig);
 *
 *   if (!validation.valid) {
 *     console.error('❌ Storage configuration errors:');
 *     validation.errors.forEach(error => console.error(`  - ${error}`));
 *     process.exit(1);
 *   }
 *
 *   console.log('✅ Storage configuration valid');
 *   return createStorageClient(providerConfig);
 * }
 * ```
 *
 */
declare function validateProviderConfig(config: ProviderConfig): {
  valid: boolean;
  errors: string[];
};
/**
 * Generates the appropriate endpoint URL for a given provider configuration.
 * This function handles automatic endpoint generation for known providers and
 * validates custom endpoints for self-hosted or specialized providers.
 *
 * @param config - The provider configuration
 * @returns The complete endpoint URL for the provider
 *
 * @example AWS S3 Endpoint
 * ```typescript
 * const awsConfig = createProvider('aws', {
 *   bucket: 'my-uploads',
 *   region: 'us-west-2',
 * });
 *
 * const endpoint = getProviderEndpoint(awsConfig);
 * // Returns: "https://s3.us-west-2.amazonaws.com"
 * ```
 *
 * @example Cloudflare R2 Endpoint
 * ```typescript
 * const r2Config = createProvider('cloudflareR2', {
 *   bucket: 'my-bucket',
 *   accountId: 'abc123def456',
 * });
 *
 * const endpoint = getProviderEndpoint(r2Config);
 * // Returns: "https://abc123def456.r2.cloudflarestorage.com"
 * ```
 *
 * @example DigitalOcean Spaces Endpoint
 * ```typescript
 * const spacesConfig = createProvider('digitalOceanSpaces', {
 *   bucket: 'my-space',
 *   region: 'nyc3',
 * });
 *
 * const endpoint = getProviderEndpoint(spacesConfig);
 * // Returns: "https://nyc3.digitaloceanspaces.com"
 * ```
 *
 * @example MinIO Custom Endpoint
 * ```typescript
 * const minioConfig = createProvider('minio', {
 *   endpoint: 'https://minio.mycompany.com:9000',
 *   bucket: 'uploads',
 * });
 *
 * const endpoint = getProviderEndpoint(minioConfig);
 * // Returns: "https://minio.mycompany.com:9000"
 * ```
 *
 * @throws {Error} When endpoint cannot be determined or is invalid
 */
declare function getProviderEndpoint(config: ProviderConfig): string;
//#endregion
//#region src/core/schema.d.ts
/**
 * File validation constraints for S3 schemas.
 * These constraints are applied during validation to ensure uploaded files
 * meet the specified requirements.
 *
 * @interface S3FileConstraints
 *
 * @example
 * ```typescript
 * const constraints: S3FileConstraints = {
 *   maxSize: '10MB',        // or 10485760 (bytes)
 *   minSize: '1KB',         // or 1024 (bytes)
 *   allowedTypes: ['image/jpeg', 'image/png', 'application/pdf'],
 *   allowedExtensions: ['.jpg', '.jpeg', '.png', '.pdf'],
 *   required: true,
 * };
 * ```
 */
interface S3FileConstraints {
  /** Maximum file size (string like '10MB' or number in bytes) */
  maxSize?: string | number;
  /** Minimum file size (string like '1KB' or number in bytes) */
  minSize?: string | number;
  /** Allowed MIME types (e.g., ['image/jpeg', 'application/pdf']) */
  allowedTypes?: string[];
  /** Allowed file extensions (e.g., ['.jpg', '.pdf']) */
  allowedExtensions?: string[];
  /** Whether the file is required (default: true) */
  required?: boolean;
}
/**
 * Array validation constraints for file arrays.
 * Used when validating multiple files uploaded together.
 *
 * @interface S3ArrayConstraints
 *
 * @example
 * ```typescript
 * const arrayConstraints: S3ArrayConstraints = {
 *   min: 1,      // At least 1 file required
 *   max: 10,     // Maximum 10 files allowed
 *   length: 5,   // Exactly 5 files required
 * };
 * ```
 */
interface S3ArrayConstraints {
  /** Minimum number of files in the array */
  min?: number;
  /** Maximum number of files in the array */
  max?: number;
  /** Exact number of files required (overrides min/max) */
  length?: number;
}
/**
 * Context object provided to validation functions.
 * Contains information about the file being validated and the validation environment.
 *
 * @interface S3ValidationContext
 *
 * @example
 * ```typescript
 * const validator = async (ctx: S3ValidationContext) => {
 *   console.log(`Validating ${ctx.file.name} in field ${ctx.fieldName}`);
 *
 *   if (ctx.allFiles) {
 *     const totalSize = Object.values(ctx.allFiles)
 *       .flat()
 *       .reduce((sum, file) => sum + file.size, 0);
 *
 *     return totalSize < 50 * 1024 * 1024; // Total < 50MB
 *   }
 *
 *   return true;
 * };
 * ```
 */
interface S3ValidationContext {
  /** The file being validated */
  file: File;
  /** Name of the field/property being validated */
  fieldName: string;
  /** All files in the upload (for cross-file validation) */
  allFiles?: Record<string, File | File[]>;
}
/**
 * Result object returned from validation operations.
 * Indicates whether validation passed and provides error details if it failed.
 *
 * @interface S3ValidationResult
 *
 * @example Success Result
 * ```typescript
 * const successResult: S3ValidationResult = {
 *   success: true,
 *   data: processedFile,
 * };
 * ```
 *
 * @example Error Result
 * ```typescript
 * const errorResult: S3ValidationResult = {
 *   success: false,
 *   error: {
 *     code: 'FILE_TOO_LARGE',
 *     message: 'File size exceeds 10MB limit',
 *     path: ['avatar'],
 *   },
 * };
 * ```
 */
interface S3ValidationResult {
  /** Whether validation succeeded */
  success: boolean;
  /** Error details if validation failed */
  error?: {
    /** Error code for programmatic handling */
    code: string;
    /** Human-readable error message */
    message: string;
    /** Path to the field that failed validation */
    path: string[];
  };
  /** Processed/transformed data if validation succeeded */
  data?: any;
}
/**
 * Context object provided to transform functions.
 * Contains the file and metadata for data transformation operations.
 *
 * @template T - Type of the original data being transformed
 * @interface S3TransformContext
 *
 * @example
 * ```typescript
 * const addTimestamp = async (ctx: S3TransformContext<File>) => {
 *   return {
 *     file: ctx.file,
 *     uploadedAt: new Date().toISOString(),
 *     userId: ctx.metadata?.userId,
 *     originalName: ctx.originalData.name,
 *   };
 * };
 * ```
 */
interface S3TransformContext<T = any> {
  /** The file being transformed */
  file: File;
  /** Additional metadata from the upload context */
  metadata?: Record<string, any>;
  /** The original data before transformation */
  originalData: T;
}
/**
 * Abstract base class for all S3 schema types.
 * Provides the foundation for type-safe file validation and transformation.
 *
 * This class implements the core validation pipeline:
 * 1. Type validation (_parse method)
 * 2. Custom validators (refine method)
 * 3. Data transformation (transform method)
 *
 * @template TInput - The input type expected by this schema
 * @template TOutput - The output type after validation and transformation
 * @abstract
 * @class S3Schema
 *
 * @example Creating a Custom Schema
 * ```typescript
 * class S3VideoSchema extends S3Schema<File, File> {
 *   _type = "video" as const;
 *
 *   _parse(input: unknown): S3ValidationResult {
 *     if (!(input instanceof File)) {
 *       return {
 *         success: false,
 *         error: {
 *           code: 'INVALID_TYPE',
 *           message: 'Expected File object',
 *           path: [],
 *         },
 *       };
 *     }
 *
 *     if (!input.type.startsWith('video/')) {
 *       return {
 *         success: false,
 *         error: {
 *           code: 'INVALID_VIDEO_TYPE',
 *           message: 'File must be a video',
 *           path: [],
 *         },
 *       };
 *     }
 *
 *     return { success: true, data: input };
 *   }
 *
 *   protected _clone(): this {
 *     return new S3VideoSchema() as this;
 *   }
 * }
 * ```
 */
declare abstract class S3Schema<TInput = any, TOutput = TInput> {
  protected _constraints: Record<string, any>;
  protected _transforms: Array<(ctx: S3TransformContext<TInput>) => Promise<any> | any>;
  protected _validators: Array<(ctx: S3ValidationContext) => S3ValidationResult | Promise<S3ValidationResult>>;
  protected _optional: boolean;
  /** Schema type identifier */
  abstract _type: string;
  /**
   * Abstract method for parsing and validating input data.
   * Must be implemented by concrete schema classes.
   *
   * @param input - The input data to validate
   * @returns Validation result indicating success or failure
   * @abstract
   */
  abstract _parse(input: unknown): S3ValidationResult | Promise<S3ValidationResult>;
  /**
   * Core validation method that orchestrates the entire validation pipeline.
   * Handles optional values, type validation, custom validators, and transformations.
   *
   * @param input - The input data to validate
   * @param context - Optional validation context
   * @returns Promise resolving to validation result
   *
   * @example
   * ```typescript
   * const schema = new S3FileSchema({ maxSize: '10MB' });
   * const result = await schema.validate(file, {
   *   fieldName: 'avatar',
   *   allFiles: { avatar: file },
   * });
   *
   * if (result.success) {
   *   console.log('File is valid:', result.data);
   * } else {
   *   console.error('Validation failed:', result.error);
   * }
   * ```
   */
  validate(input: unknown, context?: Partial<S3ValidationContext>): Promise<S3ValidationResult>;
  /**
   * Makes this schema optional, allowing undefined or null values.
   * Optional schemas will pass validation when no value is provided.
   *
   * @returns New schema instance that accepts optional values
   *
   * @example
   * ```typescript
   * const optionalImage = s3.image().maxFileSize('5MB').optional();
   *
   * // Both of these will pass validation
   * await optionalImage.validate(undefined); // ✅ Success
   * await optionalImage.validate(imageFile); // ✅ Success (if valid)
   * ```
   */
  optional(): S3Schema<TInput, TOutput | undefined>;
  /**
   * Adds a transformation function to process validated data.
   * Transformations are applied after validation succeeds and can modify the output.
   *
   * @template TNewOutput - The type of the transformed output
   * @param transformer - Function to transform the validated data
   * @returns New schema instance with the transformation applied
   *
   * @example Adding Metadata
   * ```typescript
   * const enhancedSchema = s3.file()
   *   .maxFileSize('10MB')
   *   .transform(async ({ file, metadata }) => ({
   *     originalName: file.name,
   *     size: file.size,
   *     uploadedBy: metadata.userId,
   *     uploadedAt: new Date().toISOString(),
   *   }));
   * ```
   *
   * @example Processing File Data
   * ```typescript
   * const processedSchema = s3.image()
   *   .transform(async ({ file }) => {
   *     const buffer = await file.arrayBuffer();
   *     const hash = await crypto.subtle.digest('SHA-256', buffer);
   *     return {
   *       file,
   *       hash: Array.from(new Uint8Array(hash))
   *         .map(b => b.toString(16).padStart(2, '0'))
   *         .join(''),
   *     };
   *   });
   * ```
   */
  transform<TNewOutput>(transformer: (ctx: S3TransformContext<TOutput>) => Promise<TNewOutput> | TNewOutput): S3Schema<TInput, TNewOutput>;
  /**
   * Adds a custom validation function with a custom error message.
   * Refinements are executed after basic type validation but before transformations.
   *
   * @param validator - Function that returns true if validation passes
   * @param message - Error message to show if validation fails
   * @returns New schema instance with the custom validation
   *
   * @example File Name Validation
   * ```typescript
   * const strictSchema = s3.file()
   *   .refine(
   *     async ({ file }) => !file.name.includes(' '),
   *     'File name cannot contain spaces'
   *   )
   *   .refine(
   *     async ({ file }) => file.name.length <= 50,
   *     'File name must be 50 characters or less'
   *   );
   * ```
   *
   * @example Cross-File Validation
   * ```typescript
   * const totalSizeSchema = s3.file()
   *   .refine(
   *     async ({ allFiles }) => {
   *       if (!allFiles) return true;
   *       const totalSize = Object.values(allFiles)
   *         .flat()
   *         .reduce((sum, file) => sum + file.size, 0);
   *       return totalSize <= 100 * 1024 * 1024; // 100MB total
   *     },
   *     'Total upload size cannot exceed 100MB'
   *   );
   * ```
   */
  refine(validator: (ctx: S3ValidationContext) => boolean | Promise<boolean>, message: string): this;
  /**
   * Creates a deep clone of this schema instance.
   * Used internally to ensure immutability when chaining methods.
   *
   * @returns Cloned schema instance
   * @protected
   * @abstract
   */
  protected abstract _clone(): this;
}
/**
 * Schema for validating individual File objects with comprehensive constraints.
 * This is the core schema for handling file uploads with size, type, and extension validation.
 *
 * @class S3FileSchema
 * @extends S3Schema<File, File>
 *
 * @example Basic File Validation
 * ```typescript
 * const documentSchema = new S3FileSchema({
 *   maxSize: '10MB',
 *   allowedTypes: ['application/pdf', 'application/msword'],
 *   allowedExtensions: ['.pdf', '.doc', '.docx'],
 * });
 *
 * // Use in router
 * const router = s3.createRouter({
 *   document: documentSchema,
 * });
 * ```
 *
 * @example Chainable API
 * ```typescript
 * const imageSchema = s3.file()
 *   .maxFileSize('5MB')
 *   .types(['image/jpeg', 'image/png', 'image/webp'])
 *   .extensions(['.jpg', '.jpeg', '.png', '.webp'])
 *   .refine(
 *     async ({ file }) => file.name.length <= 100,
 *     'Filename must be 100 characters or less'
 *   );
 * ```
 *
 * @example With Lifecycle Hooks
 * ```typescript
 * const trackedSchema = new S3FileSchema({ maxSize: '50MB' })
 *   .onUploadStart(async ({ file, metadata }) => {
 *     console.log(`Starting upload: ${file.name}`);
 *     await logUploadStart(file.name, metadata.userId);
 *   })
 *   .onUploadComplete(async ({ file, url, key }) => {
 *     console.log(`Upload complete: ${file.name} -> ${url}`);
 *     await notifyUploadComplete(file.name, url);
 *   })
 *   .onUploadError(async ({ file, error }) => {
 *     console.error(`Upload failed: ${file.name}`, error);
 *     await logUploadError(file.name, error);
 *   });
 * ```
 */
declare class S3FileSchema extends S3Schema<File, File> {
  protected constraints: S3FileConstraints;
  _type: "file";
  /**
   * Creates a new S3FileSchema instance with the specified constraints.
   *
   * @param constraints - File validation constraints
   *
   * @example
   * ```typescript
   * const schema = new S3FileSchema({
   *   maxSize: '10MB',
   *   minSize: '1KB',
   *   allowedTypes: ['image/jpeg', 'image/png'],
   *   allowedExtensions: ['.jpg', '.jpeg', '.png'],
   *   required: true,
   * });
   * ```
   */
  constructor(constraints?: S3FileConstraints);
  _parse(input: unknown): S3ValidationResult;
  /**
   * Sets the maximum file size constraint.
   *
   * @deprecated Use `maxFileSize()` instead. This method will be removed in a future version.
   * @param size - Maximum size as string (e.g., '10MB', '500KB') or number (bytes)
   * @returns New schema instance with max size constraint
   *
   * @example
   * ```typescript
   * const schema = s3.file().maxFileSize('10MB');
   * const schema2 = s3.file().maxFileSize(10485760); // 10MB in bytes
   * ```
   */
  max(size: string | number): S3FileSchema;
  /**
   * Sets the maximum file size constraint.
   *
   * @param size - Maximum size as string (e.g., '10MB', '500KB') or number (bytes)
   * @returns New schema instance with max size constraint
   *
   * @example
   * ```typescript
   * const schema = s3.file().maxFileSize('10MB');
   * const schema2 = s3.file().maxFileSize(10485760); // 10MB in bytes
   * ```
   */
  maxFileSize(size: string | number): S3FileSchema;
  /**
   * Sets the minimum file size constraint.
   *
   * @param size - Minimum size as string (e.g., '1KB', '100B') or number (bytes)
   * @returns New schema instance with min size constraint
   *
   * @example
   * ```typescript
   * const schema = s3.file().min('1KB');
   * const schema2 = s3.file().min(1024); // 1KB in bytes
   * ```
   */
  min(size: string | number): S3FileSchema;
  /**
   * Sets the allowed MIME types constraint.
   *
   * @param allowedTypes - Array of allowed MIME types
   * @returns New schema instance with MIME type constraint
   *
   * @example
   * ```typescript
   * const imageSchema = s3.file().types([
   *   'image/jpeg',
   *   'image/png',
   *   'image/webp'
   * ]);
   *
   * const documentSchema = s3.file().types([
   *   'application/pdf',
   *   'application/msword',
   *   'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
   * ]);
   * ```
   */
  types(allowedTypes: string[]): S3FileSchema;
  /**
   * Sets the allowed file extensions constraint.
   *
   * @param allowedExtensions - Array of allowed file extensions (with or without dots)
   * @returns New schema instance with extension constraint
   *
   * @example
   * ```typescript
   * const imageSchema = s3.file().extensions(['.jpg', '.jpeg', '.png']);
   * const docSchema = s3.file().extensions(['pdf', 'doc', 'docx']); // dots optional
   * ```
   */
  extensions(allowedExtensions: string[]): S3FileSchema;
  /**
   * Creates an array schema that validates multiple files of this type with a maximum count.
   * This is a convenience method for creating arrays with a maximum file limit.
   *
   * @param maxCount - Maximum number of files allowed
   * @returns New array schema instance with maximum constraint
   *
   * @example
   * ```typescript
   * const gallerySchema = s3.image()
   *   .maxFileSize('2MB')
   *   .maxFiles(6); // Maximum 6 images, each max 2MB
   *
   * const documentsSchema = s3.file()
   *   .types(['application/pdf'])
   *   .maxFiles(5); // Maximum 5 PDF files
   * ```
   */
  maxFiles(maxCount: number): S3ArraySchema<this>;
  protected _clone(): this;
  /**
   * Adds middleware to process requests before file upload.
   * Middleware can modify metadata, perform authentication, or add custom logic.
   *
   * @template TMetadata - Type of metadata returned by middleware
   * @param middleware - Function to process the request and return metadata
   * @returns S3Route instance with middleware applied
   *
   * @example Authentication Middleware
   * ```typescript
   * const authenticatedUpload = s3.file()
   *   .maxFileSize('10MB')
   *   .middleware(async ({ req }) => {
   *     const user = await authenticateRequest(req);
   *     if (!user) throw new Error('Unauthorized');
   *
   *     return {
   *       userId: user.id,
   *       organizationId: user.organizationId,
   *     };
   *   });
   * ```
   *
   * @example Rate Limiting Middleware
   * ```typescript
   * const rateLimitedUpload = s3.file()
   *   .middleware(async ({ req, file }) => {
   *     const clientId = getClientId(req);
   *     await checkRateLimit(clientId, file.size);
   *
   *     return { uploadedBy: clientId };
   *   });
   * ```
   */
  middleware<TMetadata$1>(middleware: (ctx: {
    req: any;
    file: {
      name: string;
      size: number;
      type: string;
    };
    metadata: any;
  }) => Promise<TMetadata$1> | TMetadata$1): S3Route<this, TMetadata$1>;
  /**
   * Adds a hook that executes when file upload starts.
   * Useful for logging, notifications, or initializing upload tracking.
   *
   * @param hook - Function to execute on upload start
   * @returns S3Route instance with upload start hook
   *
   * @example Upload Logging
   * ```typescript
   * const trackedUpload = s3.file()
   *   .onUploadStart(async ({ file, metadata }) => {
   *     console.log(`Upload started: ${file.name} (${file.size} bytes)`);
   *     await logUploadStart({
   *       fileName: file.name,
   *       fileSize: file.size,
   *       userId: metadata.userId,
   *       timestamp: new Date(),
   *     });
   *   });
   * ```
   *
   * @example Progress Initialization
   * ```typescript
   * const progressTrackedUpload = s3.file()
   *   .onUploadStart(async ({ file, metadata }) => {
   *     await initializeUploadProgress(metadata.uploadId, {
   *       fileName: file.name,
   *       totalSize: file.size,
   *       status: 'started',
   *     });
   *   });
   * ```
   */
  onUploadStart(hook: (ctx: {
    file: {
      name: string;
      size: number;
      type: string;
    };
    metadata: any;
  }) => Promise<void> | void): S3Route<this, any>;
  /**
   * Adds a hook that executes when file upload completes successfully.
   * Useful for post-processing, notifications, or updating databases.
   *
   * @param hook - Function to execute on upload completion
   * @returns S3Route instance with upload complete hook
   *
   * @example Database Update
   * ```typescript
   * const dbTrackedUpload = s3.file()
   *   .onUploadComplete(async ({ file, url, key, metadata }) => {
   *     await db.files.create({
   *       name: file.name,
   *       size: file.size,
   *       type: file.type,
   *       url: url,
   *       key: key,
   *       uploadedBy: metadata.userId,
   *       uploadedAt: new Date(),
   *     });
   *   });
   * ```
   *
   * @example Notification System
   * ```typescript
   * const notificationUpload = s3.file()
   *   .onUploadComplete(async ({ file, url, metadata }) => {
   *     await sendNotification({
   *       userId: metadata.userId,
   *       message: `File "${file.name}" uploaded successfully`,
   *       fileUrl: url,
   *     });
   *   });
   * ```
   */
  onUploadComplete(hook: (ctx: {
    file: {
      name: string;
      size: number;
      type: string;
    };
    metadata: any;
    url?: string;
    key?: string;
  }) => Promise<void> | void): S3Route<this, any>;
  /**
   * Adds a hook that executes when file upload fails.
   * Useful for error logging, cleanup, or user notifications.
   *
   * @param hook - Function to execute on upload error
   * @returns S3Route instance with upload error hook
   *
   * @example Error Logging
   * ```typescript
   * const errorLoggedUpload = s3.file()
   *   .onUploadError(async ({ file, error, metadata }) => {
   *     console.error(`Upload failed: ${file.name}`, error);
   *     await logUploadError({
   *       fileName: file.name,
   *       error: error.message,
   *       userId: metadata.userId,
   *       timestamp: new Date(),
   *     });
   *   });
   * ```
   *
   * @example User Notification
   * ```typescript
   * const userNotifiedUpload = s3.file()
   *   .onUploadError(async ({ file, error, metadata }) => {
   *     await sendErrorNotification({
   *       userId: metadata.userId,
   *       message: `Failed to upload "${file.name}": ${error.message}`,
   *     });
   *   });
   * ```
   */
  onUploadError(hook: (ctx: {
    file: {
      name: string;
      size: number;
      type: string;
    };
    metadata: any;
    error: Error;
  }) => Promise<void> | void): S3Route<this, any>;
  private _parseSize;
  private _formatSize;
}
declare class S3ImageSchema extends S3FileSchema {
  constructor(constraints?: S3FileConstraints);
  formats(formats: string[]): S3ImageSchema;
  /**
   * @deprecated Use `maxFileSize()` instead. This method will be removed in a future version.
   */
  max(size: string | number): S3ImageSchema;
  /**
   * Sets the maximum file size constraint.
   *
   * @param size - Maximum size as string (e.g., '10MB', '500KB') or number (bytes)
   * @returns New schema instance with max size constraint
   *
   * @example
   * ```typescript
   * const schema = s3.image().maxFileSize('10MB');
   * const schema2 = s3.image().maxFileSize(10485760); // 10MB in bytes
   * ```
   */
  maxFileSize(size: string | number): S3ImageSchema;
  min(size: string | number): S3ImageSchema;
  types(allowedTypes: string[]): S3ImageSchema;
  extensions(allowedExtensions: string[]): S3ImageSchema;
  /**
   * Creates an array schema that validates multiple images with a maximum count.
   * This is a convenience method for creating image arrays with a maximum file limit.
   *
   * @param maxCount - Maximum number of images allowed
   * @returns New array schema instance with maximum constraint
   *
   * @example
   * ```typescript
   * const gallerySchema = s3.image()
   *   .maxFileSize('2MB')
   *   .formats(['jpeg', 'png'])
   *   .maxFiles(6); // Maximum 6 images, each max 2MB
   * ```
   */
  maxFiles(maxCount: number): S3ArraySchema<this>;
  protected _clone(): this;
}
declare class S3ArraySchema<T extends S3Schema> extends S3Schema<File[], File[]> {
  private elementSchema;
  private arrayConstraints;
  _type: "array";
  constructor(elementSchema: T, arrayConstraints?: S3ArrayConstraints);
  _parse(input: unknown): Promise<S3ValidationResult>;
  min(count: number): S3ArraySchema<T>;
  max(count: number): S3ArraySchema<T>;
  length(count: number): S3ArraySchema<T>;
  protected _clone(): this;
}
declare class S3ObjectSchema<T extends Record<string, S3Schema>> extends S3Schema<{ [K in keyof T]: T[K] extends S3Schema<any, infer U> ? U : never }, { [K in keyof T]: T[K] extends S3Schema<any, infer U> ? U : never }> {
  private shape;
  _type: "object";
  constructor(shape: T);
  _parse(input: unknown): Promise<S3ValidationResult>;
  protected _clone(): this;
}
type InferS3Input<T extends S3Schema> = T extends S3Schema<infer I, any> ? I : never;
type InferS3Output<T extends S3Schema> = T extends S3Schema<any, infer O> ? O : never;
//#endregion
//#region src/core/storage/client.d.ts
/**
 * Creates and caches an AWS client instance using aws4fetch
 */
/**
 * Creates and caches an AWS client instance using aws4fetch.
 * This function creates a lightweight S3-compatible client that works with multiple providers.
 * The client is cached for performance and reused across requests.
 *
 * @param uploadConfig - Optional upload configuration. If not provided, uses global config.
 * @returns Configured AwsClient instance
 * @throws {Error} If configuration is missing or invalid
 *
 * @example Basic Usage
 * ```typescript
 * const client = createS3Client(config);
 *
 * // Use with aws4fetch methods
 * const response = await client.fetch('https://bucket.s3.amazonaws.com/file.jpg');
 * ```
 *
 * @example Provider-Specific Clients
 * ```typescript
 * // AWS S3 client
 * const awsClient = createS3Client(awsConfig);
 *
 * // Cloudflare R2 client
 * const r2Client = createS3Client(r2Config);
 *
 * // Both use the same interface
 * ```
 *
 */
declare function createS3Client(uploadConfig?: UploadConfig): AwsClient;
/**
 * Resets the AWS client instance (useful for testing)
 */
declare function resetS3Client(): void;
/**
 * Options for generating presigned URLs for file uploads.
 * These URLs allow clients to upload files directly to S3 without exposing credentials.
 *
 * @interface PresignedUrlOptions
 *
 * @example
 * ```typescript
 * const options: PresignedUrlOptions = {
 *   key: 'uploads/user-123/avatar.jpg',
 *   contentType: 'image/jpeg',
 *   contentLength: 1024000, // 1MB
 *   expiresIn: 3600, // 1 hour
 *   metadata: {
 *     userId: '123',
 *     uploadedBy: 'web-app',
 *   },
 * };
 * ```
 */
interface PresignedUrlOptions {
  /** S3 object key (file path) where the file will be stored */
  key: string;
  /** MIME type of the file (optional to avoid signing issues) */
  contentType?: string;
  /** Expected file size in bytes (for validation) */
  contentLength?: number;
  /** URL expiration time in seconds (default: 3600 = 1 hour) */
  expiresIn?: number;
  /** Custom metadata to attach to the uploaded object */
  metadata?: Record<string, string>;
}
/**
 * Result object returned from presigned URL generation.
 * Contains the URL and metadata needed for uploading files.
 *
 * @interface PresignedUrlResult
 *
 * @example
 * ```typescript
 * const result: PresignedUrlResult = {
 *   url: 'https://bucket.s3.amazonaws.com/uploads/file.jpg?AWSAccessKeyId=...',
 *   key: 'uploads/file.jpg',
 *   fields: {
 *     'Content-Type': 'image/jpeg',
 *     'x-amz-meta-user-id': '123',
 *   },
 * };
 *
 * // Use the URL for direct upload
 * await fetch(result.url, {
 *   method: 'PUT',
 *   headers: result.fields,
 *   body: file,
 * });
 * ```
 */
interface PresignedUrlResult {
  /** The presigned URL for uploading the file */
  url: string;
  /** The S3 object key where the file will be stored */
  key: string;
  /** Additional form fields required for the upload (for POST uploads) */
  fields?: Record<string, string>;
}
interface FileKeyOptions {
  originalName: string;
  userId?: string;
  prefix?: string;
  preserveExtension?: boolean;
  addTimestamp?: boolean;
  addRandomId?: boolean;
}
interface UploadProgress {
  loaded: number;
  total: number;
  percentage: number;
  key: string;
  progress?: number;
  uploadSpeed?: number;
  eta?: number;
}
type ProgressCallback = (progress: UploadProgress) => void;
interface ListFilesOptions {
  prefix?: string;
  maxFiles?: number;
  includeMetadata?: boolean;
  sortBy?: "key" | "size" | "modified";
  sortOrder?: "asc" | "desc";
}
interface PaginatedListOptions extends ListFilesOptions {
  pageSize?: number;
  continuationToken?: string;
}
interface FileInfo {
  key: string;
  url: string;
  size: number;
  contentType: string;
  lastModified: Date;
  etag: string;
  metadata?: Record<string, string>;
}
interface ListFilesResult {
  files: FileInfo[];
  continuationToken?: string;
  isTruncated: boolean;
  totalCount?: number;
}
interface FileInfoResult {
  key: string;
  info: FileInfo | null;
  error?: string;
}
interface FileValidationResult {
  valid: boolean;
  errors: string[];
  warnings: string[];
  info: FileInfo;
}
interface ValidationRules {
  maxSize?: number;
  minSize?: number;
  allowedTypes?: string[];
  requiredExtensions?: string[];
  customValidators?: ((info: FileInfo) => boolean | string)[];
}
interface DeleteFilesResult {
  deleted: string[];
  errors: DeleteError[];
}
interface DeleteError {
  key: string;
  code: string;
  message: string;
}
interface DeleteByPrefixResult {
  filesFound: number;
  deleted: string[];
  errors: DeleteError[];
  dryRun: boolean;
}
//#endregion
//#region src/core/storage/storage-api.d.ts
declare class StorageInstance {
  private readonly config;
  constructor(config: UploadConfig);
  /**
   * Get the current configuration (read-only)
   */
  getConfig(): Readonly<UploadConfig>;
  /**
   * Get provider information
   */
  getProviderInfo(): {
    provider: "aws" | "cloudflare-r2" | "digitalocean-spaces" | "minio" | "azure-blob" | "ibm-cloud" | "oracle-oci" | "wasabi" | "backblaze-b2" | "storj-dcs" | "telnyx-storage" | "tigris-data" | "cloudian-hyperstore" | "gcs" | "s3-compatible";
    bucket: string;
    region: string | undefined;
  };
  list: {
    files: (options?: ListFilesOptions) => Promise<FileInfo[]>;
    paginated: (options?: PaginatedListOptions) => Promise<ListFilesResult>;
    byExtension: (extension: string, prefix?: string) => Promise<FileInfo[]>;
    bySize: (minSize?: number, maxSize?: number, prefix?: string) => Promise<FileInfo[]>;
    byDate: (fromDate?: Date, toDate?: Date, prefix?: string) => Promise<FileInfo[]>;
    directories: (prefix?: string) => Promise<string[]>;
    paginatedGenerator: (options?: PaginatedListOptions) => AsyncGenerator<FileInfo[], any, any>;
  };
  metadata: {
    getInfo: (key: string) => Promise<FileInfo>;
    getBatch: (keys: string[]) => Promise<FileInfoResult[]>;
    getSize: (key: string) => Promise<number>;
    getContentType: (key: string) => Promise<string>;
    getLastModified: (key: string) => Promise<Date>;
    getCustom: (key: string) => Promise<Record<string, string>>;
    setCustom: (key: string, metadata: Record<string, string>) => Promise<void>;
  };
  download: {
    presignedUrl: (key: string, expiresIn?: number) => Promise<string>;
    url: (key: string) => string;
  };
  upload: {
    file: (file: File | Buffer, key: string, options?: any) => Promise<string>;
    presignedUrl: (options: PresignedUrlOptions) => Promise<PresignedUrlResult>;
    presignedBatch: (requests: PresignedUrlOptions[]) => Promise<PresignedUrlResult[]>;
    generateKey: (options: FileKeyOptions) => string;
  };
  validation: {
    exists: (key: string) => Promise<boolean>;
    existsWithInfo: (key: string) => Promise<FileInfo | null>;
    validateFile: (key: string, rules: ValidationRules) => Promise<FileValidationResult>;
    validateFiles: (keys: string[], rules: ValidationRules) => Promise<FileValidationResult[]>;
    connection: () => Promise<{
      success: boolean;
      error?: string;
    }>;
  };
  delete: {
    file: (key: string) => Promise<void>;
    files: (keys: string[]) => Promise<DeleteFilesResult>;
    byPrefix: (prefix: string, options?: {
      dryRun?: boolean;
      maxFiles?: number;
    }) => Promise<DeleteByPrefixResult>;
  };
}
/**
 * Create a new storage instance with the given configuration
 */
declare function createStorage(config: UploadConfig): StorageInstance;
//#endregion
//#region src/core/config/upload-config.d.ts
/**
 * Creates a config-aware S3 builder instance with schema builders and router factory.
 * This provides the `s3` object returned from `createUploadConfig().build()`.
 *
 * @internal
 * @param config - The upload configuration to bind to this instance
 * @returns An object with schema builders and router factory
 *
 * @example
 * ```typescript
 * const { s3 } = createUploadConfig().provider("aws", {...}).build();
 *
 * // Use schema builders
 * const imageSchema = s3.image({ maxSize: '5MB' });
 * const fileSchema = s3.file({ allowedTypes: ['application/pdf'] });
 *
 * // Create router with schemas
 * const router = s3.createRouter({
 *   avatarUpload: s3.image().maxFileSize('2MB'),
 *   documentUpload: s3.file({ maxSize: '10MB' }),
 * });
 * ```
 */
declare function createS3Instance(config: UploadConfig): {
  /**
   * Creates a file schema for general file uploads with optional constraints.
   *
   * @param constraints - Optional file validation constraints
   * @returns A new S3FileSchema instance
   *
   * @example
   * ```typescript
   * const pdfSchema = s3.file({
   *   maxSize: '10MB',
   *   allowedTypes: ['application/pdf'],
   * });
   * ```
   */
  readonly file: (constraints?: S3FileConstraints) => S3FileSchema;
  /**
   * Creates an image schema with image-specific validation and constraints.
   *
   * @param constraints - Optional image validation constraints
   * @returns A new S3ImageSchema instance
   *
   * @example
   * ```typescript
   * const avatarSchema = s3.image({
   *   maxSize: '5MB',
   *   allowedTypes: ['image/jpeg', 'image/png'],
   * });
   * ```
   */
  readonly image: (constraints?: S3FileConstraints) => S3ImageSchema;
  /**
   * Creates an object schema for structured data validation.
   *
   * @template T - The shape of the object schema
   * @param shape - Object defining the expected structure
   * @returns A new S3ObjectSchema instance
   *
   * @example
   * ```typescript
   * const metadataSchema = s3.object({
   *   title: 'string',
   *   tags: 'array',
   *   userId: 'string',
   * });
   * ```
   */
  readonly object: <T extends Record<string, any>>(shape: T) => S3ObjectSchema<T>;
  /**
   * Creates a config-aware router with the provided route definitions.
   * Routes can be schema objects or S3Route instances.
   *
   * @template TRoutes - The routes object type
   * @param routes - Object mapping route names to schemas or routes
   * @returns A configured S3Router instance
   *
   * @example
   * ```typescript
   * const router = s3.createRouter({
   *   // Using schema builders
   *   imageUpload: s3.image().maxFileSize('5MB'),
   *   documentUpload: s3.file({ maxSize: '10MB' }),
   *
   *   // Using route with middleware
   *   avatarUpload: s3.image()
   *     .maxFileSize('2MB')
   *     .middleware(async ({ metadata }) => ({
   *       ...metadata,
   *       userId: metadata.userId || 'anonymous',
   *     })),
   * });
   * ```
   */
  readonly createRouter: <TRoutes$1 extends Record<string, any>>(routes: TRoutes$1) => S3Router<{ [K in keyof TRoutes$1]: TRoutes$1[K] extends S3Route<any, any> ? TRoutes$1[K] : S3Route<any, any> }>;
};
/**
 * Complete upload configuration interface defining all aspects of file upload behavior.
 * This configuration is created by the UploadConfigBuilder and used throughout the system.
 *
 * @interface UploadConfig
 *
 * @example
 * ```typescript
 * const config: UploadConfig = {
 *   provider: {
 *     provider: "aws",
 *     bucket: "my-bucket",
 *     region: "us-east-1",
 *     accessKeyId: "...",
 *     secretAccessKey: "...",
 *   },
 *   defaults: {
 *     maxFileSize: '10MB',
 *     acl: 'public-read',
 *   },
 *   paths: {
 *     prefix: 'uploads',
 *     generateKey: (file, metadata) => `${metadata.userId}/${file.name}`,
 *   },
 * };
 * ```
 */
interface UploadConfig {
  /** Storage provider configuration (AWS S3, Cloudflare R2, etc.) */
  provider: ProviderConfig;
  /** Enable debug logging */
  debug?: boolean;
  /** Enable metrics collection */
  enableMetrics?: boolean;
  /** Default constraints and settings applied to all uploads */
  defaults?: {
    /** Maximum file size (string like '10MB' or number in bytes) */
    maxFileSize?: string | number;
    /** Allowed MIME types (e.g., ['image/*', 'application/pdf']) */
    allowedFileTypes?: string[];
    /** S3 ACL setting ('public-read', 'private', etc.) */
    acl?: string;
    /** Default metadata attached to all uploads */
    metadata?: Record<string, any>;
  };
  /** Path configuration for organizing uploaded files */
  paths?: {
    /** Global prefix prepended to all file paths */
    prefix?: string;
    /**
     * Global key generation function for creating file paths.
     * Route-level paths will be nested within this structure.
     *
     * @param file - File information object
     * @param metadata - Upload metadata from the request
     * @returns The generated file key/path
     */
    generateKey?: (file: {
      name: string;
      type: string;
    }, metadata: any) => string;
  };
  /** Security and access control settings */
  security?: {
    /** Whether authentication is required for uploads */
    requireAuth?: boolean;
    /** Allowed origins for CORS (if applicable) */
    allowedOrigins?: string[];
    /** Rate limiting configuration */
    rateLimiting?: {
      /** Maximum uploads per window */
      maxUploads?: number;
      /** Time window in milliseconds */
      windowMs?: number;
    };
  };
  /** Lifecycle hooks for upload events */
  hooks?: {
    /**
     * Called when an upload starts
     * @param ctx - Context object with file and metadata
     */
    onUploadStart?: (ctx: {
      file: any;
      metadata: any;
    }) => Promise<void> | void;
    /**
     * Called when an upload completes successfully
     * @param ctx - Context object with file, URL, and metadata
     */
    onUploadComplete?: (ctx: {
      file: any;
      url: string;
      metadata: any;
    }) => Promise<void> | void;
    /**
     * Called when an upload fails
     * @param ctx - Context object with file, error, and metadata
     */
    onUploadError?: (ctx: {
      file: any;
      error: Error;
      metadata: any;
    }) => Promise<void> | void;
  };
}
/**
 * Builder class for creating upload configurations with a fluent API.
 * Provides type-safe configuration of providers, defaults, paths, security, and hooks.
 *
 * @class UploadConfigBuilder
 *
 * @example Basic Usage
 * ```typescript
 * const config = new UploadConfigBuilder()
 *   .provider("aws", { bucket: "my-bucket", region: "us-east-1" })
 *   .defaults({ maxFileSize: '10MB' })
 *   .build();
 * ```
 *
 * @example Advanced Configuration
 * ```typescript
 * const config = new UploadConfigBuilder()
 *   .provider("cloudflareR2", {
 *     accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
 *     bucket: "uploads",
 *     accessKeyId: process.env.R2_ACCESS_KEY!,
 *     secretAccessKey: process.env.R2_SECRET_KEY!,
 *     region: "auto",
 *   })
 *   .defaults({
 *     maxFileSize: '50MB',
 *     allowedFileTypes: ['image/*', 'video/*'],
 *     acl: 'public-read',
 *   })
 *   .paths({
 *     prefix: 'user-content',
 *     generateKey: (file, metadata) => {
 *       const userId = metadata.userId || 'anonymous';
 *       const timestamp = Date.now();
 *       return `${userId}/${timestamp}/${file.name}`;
 *     },
 *   })
 *   .security({
 *     requireAuth: true,
 *     allowedOrigins: ['https://myapp.com'],
 *     rateLimiting: { maxUploads: 10, windowMs: 60000 },
 *   })
 *   .hooks({
 *     onUploadComplete: async ({ file, url, metadata }) => {
 *       await logUpload(metadata.userId, file.name, url);
 *     },
 *   })
 *   .build();
 * ```
 */
declare class UploadConfigBuilder {
  private config;
  /**
   * Sets the storage provider with type-safe configuration.
   * Supports both direct provider config objects and type-safe provider creation.
   *
   * @overload
   * @param providerConfig - Complete provider configuration object
   * @returns This builder instance for method chaining
   *
   * @overload
   * @template T - The provider type
   * @param type - Provider type string (e.g., "aws", "cloudflareR2")
   * @param config - Type-safe configuration for the specified provider
   * @returns This builder instance for method chaining
   *
   * @example Direct Provider Config
   * ```typescript
   * builder.provider({
   *   provider: "aws",
   *   bucket: "my-bucket",
   *   region: "us-east-1",
   *   accessKeyId: "...",
   *   secretAccessKey: "...",
   * });
   * ```
   *
   * @example Type-Safe Provider Creation
   * ```typescript
   * builder.provider("aws", {
   *   bucket: "my-bucket",
   *   region: "us-east-1",
   *   accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
   *   secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
   * });
   * ```
   */
  provider(providerConfig: ProviderConfig): UploadConfigBuilder;
  provider<T extends ProviderType>(type: T, config: ProviderConfigMap[T]): UploadConfigBuilder;
  /**
   * Sets default file constraints and upload settings.
   * These defaults are applied to all routes unless overridden at the route level.
   *
   * @param defaults - Default configuration object
   * @returns This builder instance for method chaining
   *
   * @example
   * ```typescript
   * builder.defaults({
   *   maxFileSize: '10MB',
   *   allowedFileTypes: ['image/jpeg', 'image/png', 'application/pdf'],
   *   acl: 'public-read',
   *   metadata: {
   *     uploadedBy: 'system',
   *     environment: process.env.NODE_ENV,
   *   },
   * });
   * ```
   */
  defaults(defaults: UploadConfig["defaults"]): UploadConfigBuilder;
  /**
   * Configures file paths and key generation strategy.
   * Sets up how files are organized and named in the storage bucket.
   *
   * @param paths - Path configuration object
   * @returns This builder instance for method chaining
   *
   * @example Simple Prefix
   * ```typescript
   * builder.paths({
   *   prefix: 'uploads',
   * });
   * ```
   *
   * @example Custom Key Generation
   * ```typescript
   * builder.paths({
   *   prefix: 'user-content',
   *   generateKey: (file, metadata) => {
   *     const userId = metadata.userId || 'anonymous';
   *     const timestamp = Date.now();
   *     const randomId = Math.random().toString(36).substring(2, 8);
   *     const sanitizedName = file.name.replace(/[^a-zA-Z0-9.-]/g, '_');
   *     return `${userId}/${timestamp}/${randomId}/${sanitizedName}`;
   *   },
   * });
   * ```
   */
  paths(paths: UploadConfig["paths"]): UploadConfigBuilder;
  /**
   * Configures security settings including authentication and rate limiting.
   *
   * @param security - Security configuration object
   * @returns This builder instance for method chaining
   *
   * @example
   * ```typescript
   * builder.security({
   *   requireAuth: true,
   *   allowedOrigins: ['https://myapp.com', 'https://admin.myapp.com'],
   *   rateLimiting: {
   *     maxUploads: 10,
   *     windowMs: 60000, // 1 minute
   *   },
   * });
   * ```
   */
  security(security: UploadConfig["security"]): UploadConfigBuilder;
  /**
   * Adds lifecycle hooks for upload events.
   * Hooks allow you to execute custom logic at different stages of the upload process.
   *
   * @param hooks - Lifecycle hooks configuration
   * @returns This builder instance for method chaining
   *
   * @example
   * ```typescript
   * builder.hooks({
   *   onUploadStart: async ({ file, metadata }) => {
   *     console.log(`Starting upload: ${file.name}`);
   *     await logEvent('upload_start', { fileName: file.name });
   *   },
   *   onUploadComplete: async ({ file, url, metadata }) => {
   *     console.log(`Upload complete: ${file.name} -> ${url}`);
   *     await updateDatabase(metadata.userId, file.name, url);
   *     await sendNotification(metadata.userId, 'Upload complete');
   *   },
   *   onUploadError: async ({ file, error, metadata }) => {
   *     console.error(`Upload failed: ${file.name}`, error);
   *     await logError('upload_error', { fileName: file.name, error: error.message });
   *     await sendAlert('Upload failed', error);
   *   },
   * });
   * ```
   */
  hooks(hooks: UploadConfig["hooks"]): UploadConfigBuilder;
  /**
   * Enable debug mode
   * @param enabled - Whether to enable debug mode
   * @returns This builder instance for method chaining
   */
  debug(enabled?: boolean): UploadConfigBuilder;
  /**
   * Enable metrics collection
   */
  metrics(enabled?: boolean): UploadConfigBuilder;
  /**
   * Builds the final configuration and returns configured instances.
   * Validates the configuration and creates the upload config, storage instance, and S3 builder.
   *
   * @returns Object containing the built configuration and helper instances
   * @throws {Error} If provider configuration is missing or invalid
   *
   * @example
   * ```typescript
   * const { config, storage, s3 } = createUploadConfig()
   *   .provider("aws", { bucket: "my-bucket", region: "us-east-1" })
   *   .defaults({ maxFileSize: '10MB' })
   *   .build();
   *
   * // Use the storage instance
   * const files = await storage.listFiles();
   *
   * // Create routes with the s3 builder
   * const router = s3.createRouter({
   *   imageUpload: s3.image().maxFileSize('5MB'),
   *   documentUpload: s3.file({ maxSize: '10MB' }),
   * });
   * ```
   */
  build(): UploadInitResult;
}
/**
 * Result object returned from the upload configuration builder.
 * Contains the built configuration and helper instances for creating routes and managing storage.
 *
 * @interface UploadInitResult
 *
 * @example
 * ```typescript
 * const { config, storage, s3 } = createUploadConfig()
 *   .provider("aws", { bucket: "my-bucket", region: "us-east-1" })
 *   .build();
 *
 * // Access the raw configuration
 * console.log(config.provider.bucket); // "my-bucket"
 *
 * // Use storage operations
 * const files = await storage.listFiles();
 * const fileInfo = await storage.getFileInfo('path/to/file.jpg');
 *
 * // Create typed routers
 * const router = s3.createRouter({
 *   imageUpload: s3.image().maxFileSize('5MB'),
 *   documentUpload: s3.file({ maxSize: '10MB' }),
 * });
 * ```
 */
interface UploadInitResult {
  /** The complete upload configuration object */
  config: UploadConfig;
  /** Storage instance for file operations (list, delete, info, etc.) */
  storage: StorageInstance;
  /** S3 builder instance with schema builders and router factory */
  s3: ReturnType<typeof createS3Instance>;
}
/**
 * Creates a new upload configuration builder instance.
 * This is the main entry point for configuring pushduck with providers, defaults, and settings.
 *
 * @returns A new UploadConfigBuilder instance
 *
 * @example Basic AWS Setup
 * ```typescript
 * const { s3, config, storage } = createUploadConfig()
 *   .provider("aws", {
 *     bucket: process.env.AWS_BUCKET_NAME!,
 *     region: process.env.AWS_REGION!,
 *     accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
 *     secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
 *   })
 *   .defaults({
 *     maxFileSize: '10MB',
 *     acl: 'public-read',
 *   })
 *   .build();
 * ```
 *
 * @example Cloudflare R2 Setup
 * ```typescript
 * const { s3 } = createUploadConfig()
 *   .provider("cloudflareR2", {
 *     accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
 *     bucket: process.env.R2_BUCKET!,
 *     accessKeyId: process.env.CLOUDFLARE_R2_ACCESS_KEY_ID!,
 *     secretAccessKey: process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY!,
 *     region: "auto",
 *   })
 *   .paths({
 *     prefix: 'user-uploads',
 *     generateKey: (file, metadata) => {
 *       const userId = metadata.userId || 'anonymous';
 *       const timestamp = Date.now();
 *       return `${userId}/${timestamp}/${file.name}`;
 *     },
 *   })
 *   .hooks({
 *     onUploadComplete: async ({ file, url, metadata }) => {
 *       await logUpload(metadata.userId, file.name, url);
 *     },
 *   })
 *   .build();
 * ```
 *
 * @example Multi-Environment Configuration
 * ```typescript
 * const isDevelopment = process.env.NODE_ENV === 'development';
 *
 * const { s3 } = createUploadConfig()
 *   .provider(isDevelopment ? "minio" : "aws",
 *     isDevelopment
 *       ? {
 *           endpoint: "localhost:9000",
 *           bucket: "dev-uploads",
 *           accessKeyId: "minioadmin",
 *           secretAccessKey: "minioadmin",
 *           useSSL: false,
 *         }
 *       : {
 *           bucket: process.env.AWS_BUCKET_NAME!,
 *           region: process.env.AWS_REGION!,
 *           accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
 *           secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
 *         }
 *   )
 *   .defaults({
 *     maxFileSize: isDevelopment ? '50MB' : '10MB',
 *     acl: 'public-read',
 *   })
 *   .build();
 * ```
 */
declare function createUploadConfig(): UploadConfigBuilder;
//#endregion
//#region src/core/router/router-v2.d.ts
/**
 * Base context object for S3 route operations.
 * Contains the request object and optional metadata.
 *
 * @interface S3RouteContext
 */
interface S3RouteContext {
  /** The incoming HTTP request */
  req: Request;
  /** Optional metadata from middleware or other sources */
  metadata?: Record<string, any>;
}
/**
 * File metadata structure used throughout the upload process.
 * Contains essential information about the file being uploaded.
 *
 * @interface S3FileMetadata
 *
 * @example
 * ```typescript
 * const fileMetadata: S3FileMetadata = {
 *   name: 'document.pdf',
 *   size: 1048576, // 1MB in bytes
 *   type: 'application/pdf',
 * };
 * ```
 */
interface S3FileMetadata$1 {
  /** Original filename */
  name: string;
  /** File size in bytes */
  size: number;
  /** MIME type of the file */
  type: string;
}
/**
 * Extended context for middleware functions.
 * Includes file metadata along with request context.
 *
 * @interface S3MiddlewareContext
 * @extends S3RouteContext
 */
interface S3MiddlewareContext extends S3RouteContext {
  /** Metadata about the file being processed */
  file: S3FileMetadata$1;
}
/**
 * Context object for lifecycle hooks.
 * Contains file information, metadata, and upload results.
 *
 * @template T - Type of the metadata object
 * @interface S3LifecycleContext
 *
 * @example
 * ```typescript
 * const lifecycleContext: S3LifecycleContext<{ userId: string }> = {
 *   file: { name: 'image.jpg', size: 500000, type: 'image/jpeg' },
 *   metadata: { userId: 'user123' },
 *   url: 'https://bucket.s3.amazonaws.com/path/to/image.jpg',
 *   key: 'path/to/image.jpg',
 * };
 * ```
 */
interface S3LifecycleContext<T = any> {
  /** File metadata */
  file: S3FileMetadata$1;
  /** Processed metadata from middleware */
  metadata: T;
  /** Public URL of the uploaded file (available after upload) */
  url?: string;
  /** Storage key/path of the uploaded file */
  key?: string;
}
/**
 * Middleware function type for processing requests.
 * Middleware can authenticate, validate, or transform request data.
 *
 * @template TInput - Input metadata type
 * @template TOutput - Output metadata type
 *
 * @example Authentication Middleware
 * ```typescript
 * const authMiddleware: S3Middleware<{}, { userId: string }> = async ({ req }) => {
 *   const token = req.headers.get('authorization');
 *   const user = await verifyToken(token);
 *   return { userId: user.id };
 * };
 * ```
 */
type S3Middleware<TInput = any, TOutput = any> = (ctx: S3MiddlewareContext & {
  metadata: TInput;
}) => Promise<TOutput> | TOutput;
/**
 * Lifecycle hook function type for upload events.
 * Hooks are called at specific points in the upload process.
 *
 * @template T - Metadata type
 *
 * @example Upload Complete Hook
 * ```typescript
 * const onComplete: S3LifecycleHook<{ userId: string }> = async ({ file, url, metadata }) => {
 *   await logUpload(file.name, url, metadata.userId);
 * };
 * ```
 */
type S3LifecycleHook<T = any> = (ctx: S3LifecycleContext<T>) => Promise<void> | void;
/**
 * Context object provided to path generation functions.
 * Contains file information, metadata, and configuration for building file paths.
 *
 * @template TMetadata - Type of the metadata object
 * @interface PathContext
 *
 * @example
 * ```typescript
 * const pathContext: PathContext<{ userId: string, orgId: string }> = {
 *   file: { name: 'document.pdf', type: 'application/pdf' },
 *   metadata: { userId: 'user123', orgId: 'org456' },
 *   globalConfig: { prefix: 'uploads' },
 *   routeName: 'documents',
 * };
 * ```
 */
interface PathContext<TMetadata$1 = any> {
  /** File information */
  file: {
    name: string;
    type: string;
  };
  /** Metadata from middleware */
  metadata: TMetadata$1;
  /** Global configuration settings */
  globalConfig: {
    /** Global path prefix */
    prefix?: string;
    /** Global key generation function */
    generateKey?: (file: {
      name: string;
      type: string;
    }, metadata: any) => string;
  };
  /** Name of the route being processed */
  routeName: string;
}
/**
 * Configuration for hierarchical path generation at the route level.
 * Allows customization of file storage paths with composition support.
 *
 * @template TMetadata - Type of the metadata object
 * @interface S3RoutePathConfig
 *
 * @example Basic Prefix
 * ```typescript
 * const pathConfig: S3RoutePathConfig = {
 *   prefix: 'user-avatars', // Results in: uploads/user-avatars/filename.jpg
 * };
 * ```
 *
 * @example Dynamic Key Generation
 * ```typescript
 * const pathConfig: S3RoutePathConfig<{ userId: string }> = {
 *   generateKey: ({ file, metadata, routeName }) =>
 *     `${routeName}/${metadata.userId}/${Date.now()}-${file.name}`,
 * };
 * ```
 *
 * @example Suffix Approach
 * ```typescript
 * const pathConfig: S3RoutePathConfig = {
 *   suffix: 'processed', // Results in: uploads/filename.jpg/processed
 * };
 * ```
 */
interface S3RoutePathConfig<TMetadata$1 = any> {
  /** Route-level prefix that gets nested under global prefix */
  prefix?: string;
  /** Custom key generation function with full context */
  generateKey?: (ctx: PathContext<TMetadata$1>) => string;
  /** Simple suffix appended to global paths */
  suffix?: string;
}
/**
 * Individual route configuration class that handles a single upload endpoint.
 * Provides a fluent API for configuring validation, middleware, paths, and lifecycle hooks.
 *
 * @template TSchema - The schema type for validation
 * @template TMetadata - The metadata type from middleware
 * @class S3Route
 *
 * @example Basic Route
 * ```typescript
 * const imageRoute = new S3Route(
 *   s3.image().maxFileSize('5MB'),
 *   {
 *     paths: { prefix: 'images' },
 *     onUploadComplete: async ({ file, url }) => {
 *       console.log(`Image uploaded: ${file.name} -> ${url}`);
 *     },
 *   }
 * );
 * ```
 *
 * @example Fluent API
 * ```typescript
 * const userFileRoute = s3.file()
 *   .maxFileSize('10MB')
 *   .middleware(async ({ req }) => {
 *     const user = await authenticateUser(req);
 *     return { userId: user.id };
 *   })
 *   .paths({
 *     generateKey: ({ file, metadata }) =>
 *       `users/${metadata.userId}/${file.name}`,
 *   })
 *   .onUploadStart(async ({ file, metadata }) => {
 *     await logUploadStart(file.name, metadata.userId);
 *   })
 *   .onUploadComplete(async ({ file, url, metadata }) => {
 *     await updateUserFiles(metadata.userId, { name: file.name, url });
 *   });
 * ```
 */
declare class S3Route<TSchema$1 extends S3Schema = S3Schema, TMetadata$1 = any> {
  private schema;
  private config;
  /**
   * Creates a new S3Route instance.
   *
   * @param schema - The validation schema for this route
   * @param config - Optional route configuration
   */
  constructor(schema: TSchema$1, config?: S3RouteConfig<TMetadata$1>);
  /**
   * Adds middleware to process requests before file upload.
   * Middleware functions are executed in the order they are added.
   *
   * @template TNewMetadata - Type of metadata returned by the middleware
   * @param middleware - Middleware function to add
   * @returns New route instance with middleware applied
   *
   * @example Authentication Middleware
   * ```typescript
   * const authenticatedRoute = route.middleware(async ({ req }) => {
   *   const token = req.headers.get('authorization');
   *   const user = await verifyToken(token);
   *   if (!user) throw new Error('Unauthorized');
   *   return { userId: user.id, role: user.role };
   * });
   * ```
   *
   * @example Rate Limiting Middleware
   * ```typescript
   * const rateLimitedRoute = route.middleware(async ({ req, file }) => {
   *   const clientId = getClientId(req);
   *   await checkRateLimit(clientId, file.size);
   *   return { clientId };
   * });
   * ```
   */
  middleware<TNewMetadata>(middleware: S3Middleware<TMetadata$1, TNewMetadata>): S3Route<TSchema$1, TNewMetadata>;
  /**
   * Configures hierarchical path generation for uploaded files.
   * Paths are composed with global configuration for flexible file organization.
   *
   * @param paths - Path configuration options
   * @returns This route instance for chaining
   *
   * @example Prefix-based Paths
   * ```typescript
   * const route = s3.file().paths({
   *   prefix: 'user-documents', // Results in: uploads/user-documents/filename.pdf
   * });
   * ```
   *
   * @example Dynamic Path Generation
   * ```typescript
   * const route = s3.file()
   *   .middleware(async ({ req }) => ({ userId: getUserId(req) }))
   *   .paths({
   *     generateKey: ({ file, metadata, routeName }) =>
   *       `${routeName}/${metadata.userId}/${new Date().getFullYear()}/${file.name}`,
   *   });
   * ```
   *
   * @example Organized by Date
   * ```typescript
   * const route = s3.image().paths({
   *   generateKey: ({ file }) => {
   *     const date = new Date();
   *     const year = date.getFullYear();
   *     const month = String(date.getMonth() + 1).padStart(2, '0');
   *     return `images/${year}/${month}/${Date.now()}-${file.name}`;
   *   },
   * });
   * ```
   */
  paths(paths: S3RoutePathConfig<TMetadata$1>): this;
  /**
   * Adds a hook that executes when file upload starts.
   * Useful for logging, initializing progress tracking, or sending notifications.
   *
   * @param hook - Function to execute on upload start
   * @returns This route instance for chaining
   *
   * @example Upload Logging
   * ```typescript
   * const route = s3.file().onUploadStart(async ({ file, metadata }) => {
   *   console.log(`Upload started: ${file.name} by user ${metadata.userId}`);
   *   await logUploadEvent('start', file.name, metadata.userId);
   * });
   * ```
   *
   * @example Progress Initialization
   * ```typescript
   * const route = s3.file().onUploadStart(async ({ file, metadata }) => {
   *   await createUploadProgress({
   *     fileName: file.name,
   *     totalSize: file.size,
   *     userId: metadata.userId,
   *     status: 'started',
   *   });
   * });
   * ```
   */
  onUploadStart(hook: S3LifecycleHook<TMetadata$1>): this;
  /**
   * Adds a hook that executes during file upload progress.
   * Useful for real-time progress tracking and user feedback.
   *
   * @param hook - Function to execute on upload progress
   * @returns This route instance for chaining
   *
   * @example Progress Tracking
   * ```typescript
   * const route = s3.file().onUploadProgress(async ({ file, metadata, progress }) => {
   *   await updateUploadProgress(metadata.uploadId, {
   *     fileName: file.name,
   *     progress,
   *     status: progress === 100 ? 'completing' : 'uploading',
   *   });
   * });
   * ```
   *
   * @example Real-time Updates
   * ```typescript
   * const route = s3.file().onUploadProgress(async ({ file, metadata, progress }) => {
   *   await sendProgressUpdate(metadata.userId, {
   *     fileName: file.name,
   *     percentComplete: progress,
   *   });
   * });
   * ```
   */
  onUploadProgress(hook: (ctx: S3LifecycleContext<TMetadata$1> & {
    progress: number;
  }) => Promise<void> | void): this;
  /**
   * Adds a hook that executes when file upload completes successfully.
   * Ideal for database updates, post-processing, and success notifications.
   *
   * @param hook - Function to execute on upload completion
   * @returns This route instance for chaining
   *
   * @example Database Update
   * ```typescript
   * const route = s3.file().onUploadComplete(async ({ file, url, key, metadata }) => {
   *   await db.files.create({
   *     name: file.name,
   *     size: file.size,
   *     type: file.type,
   *     url: url,
   *     key: key,
   *     uploadedBy: metadata.userId,
   *     uploadedAt: new Date(),
   *   });
   * });
   * ```
   *
   * @example Post-processing
   * ```typescript
   * const route = s3.image().onUploadComplete(async ({ file, key, metadata }) => {
   *   // Generate thumbnails for images
   *   await generateThumbnails(key, {
   *     sizes: [100, 300, 600],
   *     userId: metadata.userId,
   *   });
   * });
   * ```
   *
   * @example Notification System
   * ```typescript
   * const route = s3.file().onUploadComplete(async ({ file, url, metadata }) => {
   *   await sendNotification({
   *     userId: metadata.userId,
   *     type: 'upload_success',
   *     message: `File "${file.name}" uploaded successfully`,
   *     fileUrl: url,
   *   });
   * });
   * ```
   */
  onUploadComplete(hook: S3LifecycleHook<TMetadata$1>): this;
  /**
   * Adds a hook that executes when file upload fails.
   * Essential for error logging, cleanup, and user notifications.
   *
   * @param hook - Function to execute on upload error
   * @returns This route instance for chaining
   *
   * @example Error Logging
   * ```typescript
   * const route = s3.file().onUploadError(async ({ file, error, metadata }) => {
   *   console.error(`Upload failed: ${file.name}`, error);
   *   await logUploadError({
   *     fileName: file.name,
   *     error: error.message,
   *     stack: error.stack,
   *     userId: metadata.userId,
   *     timestamp: new Date(),
   *   });
   * });
   * ```
   *
   * @example Cleanup and Retry
   * ```typescript
   * const route = s3.file().onUploadError(async ({ file, error, metadata }) => {
   *   // Clean up any partial uploads
   *   await cleanupPartialUpload(file.name, metadata.uploadId);
   *
   *   // Queue for retry if appropriate
   *   if (isRetryableError(error)) {
   *     await queueUploadRetry(file.name, metadata);
   *   }
   * });
   * ```
   *
   * @example User Notification
   * ```typescript
   * const route = s3.file().onUploadError(async ({ file, error, metadata }) => {
   *   await sendNotification({
   *     userId: metadata.userId,
   *     type: 'upload_error',
   *     message: `Failed to upload "${file.name}": ${error.message}`,
   *   });
   * });
   * ```
   */
  onUploadError(hook: (ctx: S3LifecycleContext<TMetadata$1> & {
    error: Error;
  }) => Promise<void> | void): this;
  /**
   * Internal method to get the complete route configuration.
   * Used by the router system to access schema and configuration.
   *
   * @returns Complete route configuration including schema
   * @internal
   */
  _getConfig(): S3RouteConfig<TMetadata$1> & {
    schema: TSchema$1;
  };
}
/**
 * Internal configuration interface for S3Route.
 * Contains all the configurable aspects of a route.
 *
 * @template TMetadata - Type of metadata from middleware
 * @interface S3RouteConfig
 * @internal
 */
interface S3RouteConfig<TMetadata$1 = any> {
  /** Array of middleware functions */
  middleware?: S3Middleware<any, any>[];
  /** Path configuration for file organization */
  paths?: S3RoutePathConfig<TMetadata$1>;
  /** Hook for upload start events */
  onUploadStart?: S3LifecycleHook<TMetadata$1>;
  /** Hook for upload progress events */
  onUploadProgress?: (ctx: S3LifecycleContext<TMetadata$1> & {
    progress: number;
  }) => Promise<void> | void;
  /** Hook for upload completion events */
  onUploadComplete?: S3LifecycleHook<TMetadata$1>;
  /** Hook for upload error events */
  onUploadError?: (ctx: S3LifecycleContext<TMetadata$1> & {
    error: Error;
  }) => Promise<void> | void;
}
type S3RouterDefinition = Record<string, S3Route<any, any>>;
declare class S3Router<TRoutes$1 extends S3RouterDefinition> {
  private config;
  private routes;
  constructor(routes: TRoutes$1, config: UploadConfig);
  getRoute<K$1 extends keyof TRoutes$1>(routeName: K$1): TRoutes$1[K$1] | undefined;
  getRouteNames(): (keyof TRoutes$1)[];
  get handlers(): {
    GET: (request: Request) => Promise<Response>;
    POST: (request: Request) => Promise<Response>;
  };
  /**
   * Generate presigned URLs for file uploads with client-side metadata support.
   *
   * This method orchestrates the complete presigned URL generation workflow:
   * 1. Validates the route exists
   * 2. Runs middleware chain (client metadata → enriched metadata)
   * 3. Validates files against schema
   * 4. Calls onUploadStart hooks
   * 5. Generates hierarchical file paths
   * 6. Creates presigned upload URLs
   *
   * @template K - Route name type from router definition
   * @param routeName - Name of the upload route
   * @param req - Request object for accessing headers, etc.
   * @param files - Array of file metadata (name, size, type)
   * @param metadata - Optional client-provided metadata (untrusted)
   * @returns Array of presigned URL responses
   *
   * @remarks
   * **Metadata Flow:**
   * 1. Client sends metadata from UI (untrusted)
   * 2. Handler extracts and forwards to router
   * 3. Router passes to middleware chain
   * 4. Middleware validates/enriches metadata
   * 5. Enriched metadata used in hooks and path generation
   *
   * **Security Model:**
   * - Client metadata is UNTRUSTED user input
   * - Middleware MUST validate and sanitize
   * - Server should OVERRIDE critical fields (userId, role, etc.)
   * - Never trust client identity claims
   *
   * @security
   * ⚠️ CRITICAL: Client metadata is untrusted.
   *
   * Middleware must validate all client metadata before use:
   * ```typescript
   * .middleware(async ({ req, metadata }) => {
   *   const user = await authenticateUser(req);
   *
   *   return {
   *     // Client metadata (validate before use)
   *     albumId: validateUUID(metadata?.albumId),
   *     tags: sanitizeTags(metadata?.tags),
   *
   *     // Server metadata (trusted)
   *     userId: user.id,  // From auth, NOT from client
   *     role: user.role,   // From auth, NOT from client
   *   };
   * });
   * ```
   *
   * @example Basic usage (no client metadata)
   * ```typescript
   * const results = await router.generatePresignedUrls(
   *   'imageUpload',
   *   request,
   *   [{ name: 'photo.jpg', size: 1024000, type: 'image/jpeg' }]
   * );
   * ```
   *
   * @example With client metadata
   * ```typescript
   * const results = await router.generatePresignedUrls(
   *   'imageUpload',
   *   request,
   *   [{ name: 'photo.jpg', size: 1024000, type: 'image/jpeg' }],
   *   { albumId: 'abc123', tags: ['vacation'] }  // Client metadata
   * );
   * ```
   *
   * @throws {Error} If route not found or validation fails
   */
  generatePresignedUrls<K$1 extends keyof TRoutes$1>(routeName: K$1, req: Request, files: S3FileMetadata$1[], metadata?: any): Promise<PresignedUrlResponse[]>;
  handleUploadComplete<K$1 extends keyof TRoutes$1>(routeName: K$1, req: Request, completions: UploadCompletion[]): Promise<CompletionResponse[]>;
}
interface PresignedUrlResponse {
  success: boolean;
  file: S3FileMetadata$1;
  presignedUrl?: string;
  key?: string;
  metadata?: any;
  error?: string;
}
interface UploadCompletion {
  key: string;
  file: S3FileMetadata$1;
  metadata?: any;
}
interface CompletionResponse {
  success: boolean;
  key: string;
  url?: string;
  presignedUrl?: string;
  file?: S3FileMetadata$1;
  error?: string;
}
/**
 * ✅ Config-aware router factory
 * Creates router with explicit config dependency
 */
declare function createS3RouterWithConfig<TRoutes$1 extends S3RouterDefinition>(routes: TRoutes$1, config: UploadConfig): S3Router<TRoutes$1>;
type InferRouterRoutes<T> = T extends S3Router<infer TRoutes> ? TRoutes : never;
type InferRouteInput<T> = T extends S3Route<infer TSchema, any> ? InferS3Input<TSchema> : never;
type InferRouteOutput<T> = T extends S3Route<infer TSchema, any> ? InferS3Output<TSchema> : never;
type InferRouteMetadata<T> = T extends S3Route<any, infer TMetadata> ? TMetadata : never;
type GetRoute<TRouter, TRouteName> = TRouter extends S3Router<infer TRoutes> ? TRouteName extends keyof TRoutes ? TRoutes[TRouteName] : never : never;
//#endregion
//#region src/types/index.d.ts
/**
 * Centralized Type Definitions for pushduck
 *
 * This file consolidates all type definitions to prevent circular dependencies
 * and provide a single source of truth for types used across the library.
 */
interface S3UploadedFile {
  id: string;
  name: string;
  size: number;
  type: string;
  status: "pending" | "uploading" | "success" | "error";
  progress: number;
  url?: string;
  key?: string;
  presignedUrl?: string;
  error?: string;
  file?: File;
  uploadStartTime?: number;
  uploadSpeed?: number;
  eta?: number;
}
interface S3FileMetadata {
  name: string;
  size: number;
  type: string;
}
interface UploadRouteConfig {
  endpoint?: string;
  onStart?: (files: S3FileMetadata[]) => void | Promise<void>;
  onSuccess?: (results: S3UploadedFile[]) => void | Promise<void>;
  onError?: (error: Error) => void;
  onProgress?: (progress: number) => void;
}
type S3RouteUploadConfig = UploadRouteConfig;
type RouteUploadOptions = UploadRouteConfig;
/**
 * Result object returned by upload hooks with client metadata support.
 *
 * @interface S3RouteUploadResult
 *
 * @remarks
 * This interface represents the state and control functions for file uploads.
 * The `uploadFiles` function now accepts optional metadata to pass client context.
 *
 * @example
 * ```typescript
 * const { uploadFiles, files, isUploading } = useUploadRoute('imageUpload');
 *
 * // Upload with metadata
 * await uploadFiles(selectedFiles, {
 *   albumId: album.id,
 *   tags: ['vacation']
 * });
 * ```
 */
interface S3RouteUploadResult {
  /** Array of files with upload status and progress */
  files: S3UploadedFile[];
  /**
   * Upload files with optional client-side metadata.
   *
   * @param files - Array of File objects to upload
   * @param metadata - Optional metadata object (untrusted client data)
   *
   * @security
   * Metadata is untrusted. Server middleware must validate before use.
   *
   * @example
   * ```typescript
   * // Without metadata
   * await uploadFiles(files);
   *
   * // With metadata
   * await uploadFiles(files, { albumId: '123', tags: ['vacation'] });
   * ```
   */
  uploadFiles: (files: File[], metadata?: any) => Promise<void>;
  /** Reset upload state and clear files */
  reset: () => void;
  /** Whether an upload is currently in progress */
  isUploading: boolean;
  /** Array of error messages from failed uploads */
  errors: string[];
  /** Overall progress percentage (0-100) across all files */
  progress?: number;
  /** Overall upload speed in bytes per second across all files */
  uploadSpeed?: number;
  /** Estimated time remaining in seconds for all files */
  eta?: number;
}
interface ClientConfig {
  endpoint: string;
  fetcher?: (input: RequestInfo, init?: RequestInit) => Promise<Response>;
  defaultOptions?: RouteUploadOptions;
}
interface TypedUploadedFile<TOutput = any> extends S3UploadedFile {
  metadata?: TOutput;
  constraints?: {
    maxSize?: string;
    formats?: readonly string[];
    dimensions?: {
      width?: number;
      height?: number;
    };
  };
  routeName?: string;
}
/**
 * Enhanced hook return with route-specific types and metadata support.
 *
 * @template TRouter - Router type for route name inference
 * @template TRouteName - Specific route name string
 *
 * @interface TypedRouteHook
 *
 * @remarks
 * This interface extends S3RouteUploadResult with type-safe route names
 * and enhanced file metadata. Used by the property-based client API.
 *
 * @example
 * ```typescript
 * const { uploadFiles, routeName } = upload.imageUpload();
 *
 * // Type-safe route name
 * console.log(routeName); // 'imageUpload'
 *
 * // Upload with metadata
 * await uploadFiles(files, { albumId: '123' });
 * ```
 */
interface TypedRouteHook<TRouter = any, TRouteName extends string = string> {
  /** Array of uploaded files with enhanced metadata */
  files: TypedUploadedFile[];
  /**
   * Upload files with optional client-side metadata.
   *
   * @param files - Array of File objects to upload
   * @param metadata - Optional metadata (untrusted client data)
   * @returns Promise resolving to array of upload results
   *
   * @security
   * Client metadata is untrusted and must be validated by server middleware.
   */
  uploadFiles: (files: File[], metadata?: any) => Promise<any[]>;
  /** Reset upload state */
  reset: () => void;
  /** Whether upload is in progress */
  isUploading: boolean;
  /** Array of error messages */
  errors: string[];
  /** Type-safe route name */
  routeName: TRouteName;
  /** Overall progress percentage (0-100) */
  progress?: number;
  /** Overall upload speed in bytes/second */
  uploadSpeed?: number;
  /** Estimated time remaining in seconds */
  eta?: number;
}
type RouterRouteNames<T> = T extends S3Router<infer TRoutes> ? keyof TRoutes : never;
type InferClientRouter<T> = T extends S3Router<infer TRoutes> ? { readonly [K in keyof TRoutes]: (options?: RouteUploadOptions) => TypedRouteHook<T, K extends string ? K : string> } : never;
//#endregion
export { S3ImageSchema as $, createStorage as A, PaginatedListOptions as B, S3RouterDefinition as C, UploadInitResult as D, UploadConfigBuilder as E, FileInfoResult as F, ValidationRules as G, PresignedUrlResult as H, FileKeyOptions as I, InferS3Input as J, createS3Client as K, FileValidationResult as L, DeleteError as M, DeleteFilesResult as N, createUploadConfig as O, FileInfo as P, S3FileSchema as Q, ListFilesOptions as R, S3Router as S, UploadConfig as T, ProgressCallback as U, PresignedUrlOptions as V, UploadProgress as W, S3ArraySchema as X, InferS3Output as Y, S3FileConstraints as Z, S3LifecycleHook as _, S3RouteUploadConfig as a, DigitalOceanSpacesConfig as at, S3Route as b, TypedRouteHook as c, ProviderConfig as ct, GetRoute as d, getProviderEndpoint as dt, S3ObjectSchema as et, InferRouteInput as f, validateProviderConfig as ft, S3LifecycleContext as g, InferRouterRoutes as h, S3FileMetadata as i, CloudflareR2Config as it, DeleteByPrefixResult as j, StorageInstance as k, TypedUploadedFile as l, ProviderType as lt, InferRouteOutput as m, InferClientRouter as n, AWSProviderConfig as nt, S3RouteUploadResult as o, GoogleCloudStorageConfig as ot, InferRouteMetadata as p, resetS3Client as q, RouterRouteNames as r, BaseProviderConfig as rt, S3UploadedFile as s, MinIOConfig as st, ClientConfig as t, S3Schema as tt, UploadRouteConfig as u, createProvider as ut, S3Middleware as v, createS3RouterWithConfig as w, S3RouteContext as x, S3MiddlewareContext as y, ListFilesResult as z };