import { IncomingMessage, ServerResponse, OutgoingHttpHeaders } from 'node:http';
import { Socket } from 'node:net';
import { Get, UniversalHandler, UniversalFn, Awaitable, UniversalMiddleware, RuntimeAdapterTarget, UniversalRouter, UniversalRouterInterface, EnhancedMiddleware } from '@universal-middleware/core';
import { Readable } from 'node:stream';
import { Express as Express$2 } from 'express';
import { Express as Express$1 } from 'express4';

/** Adapter options */
interface NodeRequestAdapterOptions {
    /**
     * Set the origin part of the URL to a constant value.
     * It defaults to `process.env.ORIGIN`. If neither is set,
     * the origin is computed from the protocol and hostname.
     * To determine the protocol, `req.protocol` is tried first.
     * If `trustProxy` is set, `X-Forwarded-Proto` header is used.
     * Otherwise, `req.socket.encrypted` is used.
     * To determine the hostname, `X-Forwarded-Host`
     * (if `trustProxy` is set) or `Host` header is used.
     */
    origin?: string;
    /**
     * Whether to trust `X-Forwarded-*` headers. `X-Forwarded-Proto`
     * and `X-Forwarded-Host` are used to determine the origin when
     * `origin` and `process.env.ORIGIN` are not set. `X-Forwarded-For`
     * is used to determine the IP address. The leftmost values are used
     * if multiple values are set. Defaults to true if `process.env.TRUST_PROXY`
     * is set to `1`, otherwise false.
     */
    trustProxy?: boolean;
}
/** Create a function that converts a Node HTTP request into a fetch API `Request` object */
declare function createRequestAdapter(options?: NodeRequestAdapterOptions): (req: DecoratedRequest) => Request;

declare const contextSymbol: unique symbol;
declare const requestSymbol: unique symbol;
declare const pendingMiddlewaresSymbol: unique symbol;
declare const wrappedResponseSymbol: unique symbol;
interface PossiblyEncryptedSocket extends Socket {
    encrypted?: boolean;
}
/**
 * `IncomingMessage` possibly augmented by Express-specific
 * `ip` and `protocol` properties.
 */
interface DecoratedRequest<C extends Universal.Context = Universal.Context> extends Omit<IncomingMessage, "socket"> {
    ip?: string;
    protocol?: string;
    socket?: PossiblyEncryptedSocket;
    rawBody?: Buffer | null;
    originalUrl?: string;
    params?: Record<string, string>;
    [contextSymbol]?: C;
    [requestSymbol]?: Request;
}
interface DecoratedServerResponse extends ServerResponse {
    [pendingMiddlewaresSymbol]?: ((response: Response) => Awaitable<Response | undefined>)[];
    [wrappedResponseSymbol]?: boolean;
}
/** Connect/Express style request listener/middleware */
type NodeMiddleware<In extends Universal.Context, Out extends Universal.Context> = UniversalFn<UniversalMiddleware<In, Out>, <R>(req: DecoratedRequest<In>, res: DecoratedServerResponse, next?: (err?: unknown) => void) => R>;
type NodeHandler<In extends Universal.Context> = UniversalFn<UniversalHandler<In>, <R>(req: DecoratedRequest<In>, res: DecoratedServerResponse, next?: (err?: unknown) => void) => R>;
/** Adapter options */
interface NodeAdapterHandlerOptions extends NodeRequestAdapterOptions {
}
interface NodeAdapterMiddlewareOptions extends NodeRequestAdapterOptions {
}
/**
 * Creates a request handler to be passed to http.createServer() or used as a
 * middleware in Connect-style frameworks like Express.
 */
declare function createHandler<T extends unknown[], InContext extends Universal.Context>(handlerFactory: Get<T, UniversalHandler<InContext>>, options?: NodeAdapterHandlerOptions): Get<T, NodeHandler<InContext>>;
/**
 * Creates a middleware to be passed to Connect-style frameworks like Express
 */
declare function createMiddleware<T extends unknown[], InContext extends Universal.Context, OutContext extends Universal.Context>(middlewareFactory: Get<T, UniversalMiddleware<InContext, OutContext>>, options?: NodeAdapterMiddlewareOptions): Get<T, NodeMiddleware<InContext, OutContext>>;
declare function getContext<InContext extends Universal.Context = Universal.Context>(req: DecoratedRequest): InContext;

/**
 * Send a fetch API Response into a Node.js HTTP response stream.
 */
declare function sendResponse(fetchResponse: Response, nodeResponse: DecoratedServerResponse): Promise<void>;

type Express = Express$1 | Express$2;
type ConnectMiddleware = (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void | Promise<void>;
type ConnectMiddlewareBoolean = (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => boolean | Promise<boolean>;
type WebHandler<InContext extends Universal.Context = Universal.Context, Target = unknown> = (request: Request, context?: InContext, runtime?: RuntimeAdapterTarget<Target>) => Response | undefined | Promise<Response | undefined>;
/**
 * Converts a Connect-style middleware to a web-compatible request handler.
 * @beta
 */
declare function connectToWeb(handler: ConnectMiddleware | ConnectMiddlewareBoolean): WebHandler;
/**
 * Creates an IncomingMessage object from a web Request.
 * @beta
 */
declare function createIncomingMessage(request: Request): IncomingMessage;
/**
 * Creates a custom ServerResponse object that allows for intercepting and streaming the response.
 *
 * @beta
 * @returns
 * An object containing:
 *   - res: The custom ServerResponse object.
 *   - onReadable: A function that takes a callback. The callback is invoked when the response is readable,
 *     providing an object with the readable stream, headers, and status code.
 */
declare function createServerResponse(incomingMessage: IncomingMessage): {
    res: ServerResponse<IncomingMessage>;
    onReadable: (cb: (result: {
        readable: Readable;
        headers: OutgoingHttpHeaders;
        statusCode: number;
    }) => void) => void;
};

declare class UniversalExpressRouter<T extends Express> extends UniversalRouter implements UniversalRouterInterface {
    #private;
    constructor(app: T);
    use(middleware: EnhancedMiddleware): this;
    applyCatchAll(): this;
}
declare function apply(app: Express, middlewares: EnhancedMiddleware[]): void;

export { type ConnectMiddleware, type ConnectMiddlewareBoolean, type DecoratedRequest, type DecoratedServerResponse, type NodeHandler, type NodeMiddleware, UniversalExpressRouter, type WebHandler, apply, connectToWeb, createHandler, createIncomingMessage, createMiddleware, createRequestAdapter, createServerResponse, getContext, sendResponse };
