/**
 * Parses and persists HTTP `multipart/form-data` request bodies.
 *
 * `Multipart` turns incoming byte streams into typed {@link Part} values. Text
 * parts become decoded {@link Field} values, while upload parts remain streamed
 * {@link File} values until they are collected or written to scoped temporary
 * files. The persisted representation can then be decoded with schemas for
 * request handlers that receive fields and uploaded files together.
 *
 * **Mental model**
 *
 * Multipart parsing is incremental. {@link makeChannel} consumes request body
 * chunks and emits fields or files as soon as the parser reaches each part. A
 * `File` owns a one-shot byte stream for that upload; {@link toPersisted}
 * drains those file streams into scoped paths and collects text fields into a
 * {@link Persisted} record.
 *
 * **Common tasks**
 *
 * - Parse a request body stream into {@link Part} values with {@link makeChannel}.
 * - Persist parsed parts with {@link toPersisted} before schema decoding.
 * - Decode persisted forms with {@link schemaPersisted}, {@link schemaJson},
 *   {@link PersistedFileSchema}, or {@link SingleFileSchema}.
 * - Configure parser limits with {@link limitsServices} or the `Max*` context
 *   references.
 *
 * **Gotchas**
 *
 * Multipart request bodies are usually one-shot streams. Read each file stream
 * once, and use `contentEffect` only when the file is small enough to hold in
 * memory. Paths produced by {@link toPersisted} are scoped resources and stop
 * being valid when the scope closes. Client-provided file names are metadata,
 * not trusted filesystem paths.
 *
 * **See also**
 *
 * {@link Part}, {@link Field}, {@link File}, {@link Persisted},
 * {@link makeChannel}, {@link toPersisted}.
 *
 * @since 4.0.0
 */
import * as Arr from "../../Array.ts";
import * as Cause from "../../Cause.ts";
import * as Channel from "../../Channel.ts";
import * as Context from "../../Context.ts";
import * as Data from "../../Data.ts";
import * as Effect from "../../Effect.ts";
import * as FileSystem from "../../FileSystem.ts";
import * as Inspectable from "../../Inspectable.ts";
import * as Path from "../../Path.ts";
import * as Schema from "../../Schema.ts";
import type { ParseOptions } from "../../SchemaAST.ts";
import type * as Scope from "../../Scope.ts";
import * as Stream from "../../Stream.ts";
import * as MP from "./Multipasta.ts";
/**
 * Type identifier used to brand multipart part values.
 *
 * @category type IDs
 * @since 4.0.0
 */
export declare const TypeId = "~effect/http/Multipart";
/**
 * A parsed multipart part.
 *
 * **Details**
 *
 * A part is either a text `Field` or a streamed `File`.
 *
 * @category models
 * @since 4.0.0
 */
export type Part = Field | File;
/**
 * Namespace containing shared multipart part model types.
 *
 * @since 4.0.0
 */
export declare namespace Part {
    /**
     * Common protocol implemented by multipart part values.
     *
     * **Details**
     *
     * It provides the multipart type identifier, tag, and inspectable behavior shared
     * by fields, files, and persisted files.
     *
     * @category models
     * @since 4.0.0
     */
    interface Proto extends Inspectable.Inspectable {
        readonly [TypeId]: typeof TypeId;
        readonly _tag: string;
    }
}
/**
 * Multipart form field containing a decoded text value.
 *
 * **Details**
 *
 * The `key` is the field name, `contentType` is the part media type, and `value`
 * is the decoded field content.
 *
 * @category models
 * @since 4.0.0
 */
export interface Field extends Part.Proto {
    readonly _tag: "Field";
    readonly key: string;
    readonly contentType: string;
    readonly value: string;
}
/**
 * Returns `true` when a value is a multipart `Part`.
 *
 * @category guards
 * @since 4.0.0
 */
export declare const isPart: (u: unknown) => u is Part;
/**
 * Returns `true` when a value is a multipart text `Field`.
 *
 * @category guards
 * @since 4.0.0
 */
export declare const isField: (u: unknown) => u is Field;
/**
 * Multipart file part.
 *
 * **Gotchas**
 *
 * The file content is exposed as a byte stream. `contentEffect` collects the full
 * file into memory and should be used only when the file size is acceptable.
 *
 * @category models
 * @since 4.0.0
 */
export interface File extends Part.Proto {
    readonly _tag: "File";
    readonly key: string;
    readonly name: string;
    readonly contentType: string;
    readonly content: Stream.Stream<Uint8Array, MultipartError>;
    readonly contentEffect: Effect.Effect<Uint8Array, MultipartError>;
}
/**
 * Returns `true` when a value is a multipart `File`.
 *
 * @category guards
 * @since 4.0.0
 */
export declare const isFile: (u: unknown) => u is File;
/**
 * Multipart file part that has been written to the filesystem.
 *
 * **Details**
 *
 * The `path` points to the persisted file while the scope used to persist the
 * multipart data remains open.
 *
 * @category models
 * @since 4.0.0
 */
export interface PersistedFile extends Part.Proto {
    readonly _tag: "PersistedFile";
    readonly key: string;
    readonly name: string;
    readonly contentType: string;
    readonly path: string;
}
/**
 * Returns `true` when a value is a persisted multipart file.
 *
 * @category guards
 * @since 4.0.0
 */
export declare const isPersistedFile: (u: unknown) => u is PersistedFile;
/**
 * Record representation of persisted multipart data.
 *
 * **Details**
 *
 * Field names map to text values, arrays of text values, or arrays of
 * `PersistedFile` values.
 *
 * @category models
 * @since 4.0.0
 */
export interface Persisted {
    readonly [key: string]: ReadonlyArray<PersistedFile> | ReadonlyArray<string> | string;
}
declare const MultipartErrorTypeId = "~effect/http/Multipart/MultipartError";
/**
 * Error reason carried by a `MultipartError`.
 *
 * **Details**
 *
 * It identifies parser and limit failures such as oversized files or fields, too
 * many parts, total body size limits, parse errors, and internal errors.
 *
 * @category errors
 * @since 4.0.0
 */
export declare class MultipartErrorReason extends Data.Error<{
    readonly _tag: "FileTooLarge" | "FieldTooLarge" | "BodyTooLarge" | "TooManyParts" | "InternalError" | "Parse";
    readonly cause?: unknown;
}> {
}
declare const MultipartError_base: new <A extends Record<string, any> = {}>(args: import("../../Types.ts").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
    readonly _tag: "MultipartError";
} & Readonly<A>;
/**
 * Error raised while parsing, streaming, or persisting multipart form data.
 *
 * **Details**
 *
 * The `reason` field contains the concrete `MultipartErrorReason`.
 *
 * @category errors
 * @since 4.0.0
 */
export declare class MultipartError extends MultipartError_base<{
    readonly reason: MultipartErrorReason;
}> {
    /**
     * Creates a multipart error from a reason tag and optional cause.
     *
     * @since 4.0.0
     */
    static fromReason(reason: MultipartErrorReason["_tag"], cause?: unknown): MultipartError;
    /**
     * Marks this value as a multipart error for runtime guards.
     *
     * @since 4.0.0
     */
    readonly [MultipartErrorTypeId] = "~effect/http/Multipart/MultipartError";
    /**
     * Uses the concrete multipart error reason as the public message.
     *
     * @since 4.0.0
     */
    get message(): string;
}
/**
 * Schema type for persisted multipart files.
 *
 * @category schemas
 * @since 4.0.0
 */
export interface PersistedFileSchema extends Schema.declare<PersistedFile> {
}
/**
 * Schema for persisted multipart files.
 *
 * **Details**
 *
 * The encoded form contains the field key, original file name, content type, and
 * filesystem path.
 *
 * @category schemas
 * @since 4.0.0
 */
export declare const PersistedFileSchema: PersistedFileSchema;
/**
 * Schema for an array of persisted multipart files.
 *
 * @category schemas
 * @since 4.0.0
 */
export declare const FilesSchema: Schema.$Array<PersistedFileSchema>;
/**
 * Schema for exactly one persisted multipart file.
 *
 * **Details**
 *
 * The encoded form is a one-element file array, while the decoded value is the
 * single `PersistedFile`.
 *
 * @category schemas
 * @since 4.0.0
 */
export declare const SingleFileSchema: Schema.decodeTo<PersistedFileSchema, Schema.$Array<PersistedFileSchema>>;
/**
 * Creates a decoder for persisted multipart data using the supplied schema.
 *
 * **Details**
 *
 * The returned function decodes an unknown input into the schema output and fails
 * with `SchemaError` when validation fails.
 *
 * @category schemas
 * @since 4.0.0
 */
export declare const schemaPersisted: <A, I extends Partial<Persisted>, RD, RE>(schema: Schema.Codec<A, I, RD, RE>) => (input: unknown, options?: ParseOptions) => Effect.Effect<A, Schema.SchemaError, RD>;
/**
 * Creates a decoder for a JSON-encoded field in persisted multipart data.
 *
 * **Details**
 *
 * The selected field is parsed from a JSON string and decoded with the supplied
 * schema.
 *
 * @category schemas
 * @since 4.0.0
 */
export declare const schemaJson: <A, I, RD, RE>(schema: Schema.Codec<A, I, RD, RE>, options?: ParseOptions | undefined) => {
    (field: string): (persisted: Persisted) => Effect.Effect<A, Schema.SchemaError, RD>;
    (persisted: Persisted, field: string): Effect.Effect<A, Schema.SchemaError, RD>;
};
/**
 * Builds the low-level multipart parser configuration from request headers and
 * the current fiber context.
 *
 * **Details**
 *
 * Parser limits are read from the multipart references, including maximum parts,
 * field size, file size, total body size, and field MIME type overrides.
 *
 * @category configuration
 * @since 4.0.0
 */
export declare const makeConfig: (headers: Record<string, string>) => Effect.Effect<MP.BaseConfig>;
/**
 * Creates a channel that parses multipart byte chunks into multipart parts.
 *
 * **Details**
 *
 * The channel consumes non-empty batches of `Uint8Array` chunks and emits
 * non-empty batches of parsed `Part` values, failing with `MultipartError` for
 * parser and limit failures.
 *
 * @category Parsers
 * @since 4.0.0
 */
export declare const makeChannel: <IE>(headers: Record<string, string>) => Channel.Channel<Arr.NonEmptyReadonlyArray<Part>, MultipartError | IE, void, Arr.NonEmptyReadonlyArray<Uint8Array>, IE, unknown>;
/**
 * Runs a channel of byte chunks and collects all output into a single
 * `Uint8Array`.
 *
 * **Gotchas**
 *
 * This materializes the full content in memory.
 *
 * @category converting
 * @since 4.0.0
 */
export declare const collectUint8Array: <OE, OD, R>(self: Channel.Channel<Arr.NonEmptyReadonlyArray<Uint8Array>, OE, OD, unknown, unknown, unknown, R>) => Effect.Effect<Uint8Array<ArrayBuffer>, OE, R>;
/**
 * Persists a stream of multipart parts into a record.
 *
 * **Details**
 *
 * Text fields are collected as strings, and file parts are written to files in a
 * scoped temporary directory.
 *
 * **Gotchas**
 *
 * Persisted file paths remain valid for the lifetime of the scope.
 *
 * @category converting
 * @since 4.0.0
 */
export declare const toPersisted: (stream: Stream.Stream<Part, MultipartError>, writeFile?: (path: string, file: File) => Effect.Effect<void, MultipartError, FileSystem.FileSystem>) => Effect.Effect<Persisted, MultipartError, FileSystem.FileSystem | Path.Path | Scope.Scope>;
/**
 * Creates a context containing multipart parser limit settings.
 *
 * **Details**
 *
 * The context can provide maximum part count, field size, file size, total body
 * size, and MIME types that should be parsed as fields.
 *
 * @category references
 * @since 4.0.0
 */
export declare const limitsServices: (options: {
    readonly maxParts?: number | undefined;
    readonly maxFieldSize?: FileSystem.SizeInput | undefined;
    readonly maxFileSize?: FileSystem.SizeInput | undefined;
    readonly maxTotalSize?: FileSystem.SizeInput | undefined;
    readonly fieldMimeTypes?: ReadonlyArray<string> | undefined;
}) => Context.Context<never>;
/**
 * Namespace containing multipart parser limit option types.
 *
 * @since 4.0.0
 */
export declare namespace withLimits {
    /**
     * Options for overriding multipart parser limits.
     *
     * **Details**
     *
     * These settings control maximum part count, field size, file size, total body
     * size, and MIME types that should be treated as fields instead of files.
     *
     * @category fiber refs
     * @since 4.0.0
     */
    type Options = {
        readonly maxParts?: number | undefined;
        readonly maxFieldSize?: FileSystem.SizeInput | undefined;
        readonly maxFileSize?: FileSystem.SizeInput | undefined;
        readonly maxTotalSize?: FileSystem.SizeInput | undefined;
        readonly fieldMimeTypes?: ReadonlyArray<string> | undefined;
    };
}
/**
 * Context reference for the maximum number of multipart parts allowed.
 *
 * **Details**
 *
 * The default is `undefined`, meaning no explicit part-count limit.
 *
 * @category references
 * @since 4.0.0
 */
export declare const MaxParts: Context.Reference<number | undefined>;
/**
 * Context reference for the maximum size of a multipart field value.
 *
 * **Details**
 *
 * The default limit is 10 MiB.
 *
 * @category references
 * @since 4.0.0
 */
export declare const MaxFieldSize: Context.Reference<FileSystem.SizeInput>;
/**
 * Context reference for the maximum size of a multipart file part.
 *
 * **Details**
 *
 * The default is `undefined`, meaning no explicit per-file limit.
 *
 * @category references
 * @since 4.0.0
 */
export declare const MaxFileSize: Context.Reference<FileSystem.SizeInput | undefined>;
/**
 * Context reference for MIME type fragments that should be parsed as multipart
 * fields instead of files.
 *
 * **Details**
 *
 * The default treats `application/json` parts as fields.
 *
 * @category references
 * @since 4.0.0
 */
export declare const FieldMimeTypes: Context.Reference<readonly string[]>;
export {};
//# sourceMappingURL=Multipart.d.ts.map