import React from "react";
import { RequestInfo } from "../requestInfo/types";
import type { DocumentProps, LayoutProps } from "./types.js";
type MaybePromise<T> = T | Promise<T>;
type BivariantRouteHandler<T extends RequestInfo, R> = {
    bivarianceHack(requestInfo: T): R;
}["bivarianceHack"];
export type RouteMiddleware<T extends RequestInfo = RequestInfo> = BivariantRouteHandler<T, MaybePromise<React.JSX.Element | Response | void>>;
export type ExceptHandler<T extends RequestInfo = RequestInfo> = {
    __rwExcept: true;
    handler: (error: unknown, requestInfo: T) => MaybePromise<React.JSX.Element | Response | void>;
    pathPattern?: string;
};
type RouteFunction<T extends RequestInfo = RequestInfo> = BivariantRouteHandler<T, MaybePromise<Response>>;
type RouteComponent<T extends RequestInfo = RequestInfo> = BivariantRouteHandler<T, MaybePromise<React.JSX.Element | Response | void>>;
type RouteHandler<T extends RequestInfo = RequestInfo> = RouteFunction<T> | RouteComponent<T> | readonly [...RouteMiddleware<T>[], RouteFunction<T> | RouteComponent<T>];
declare const METHOD_VERBS: readonly ["delete", "get", "head", "patch", "post", "put"];
export type MethodVerb = (typeof METHOD_VERBS)[number];
export type MethodHandlers<T extends RequestInfo = RequestInfo> = {
    [K in MethodVerb]?: RouteHandler<T>;
} & {
    config?: {
        disable405?: true;
        disableOptions?: true;
    };
    custom?: {
        [method: string]: RouteHandler<T>;
    };
};
export type Route<T extends RequestInfo = RequestInfo> = RouteMiddleware<T> | RouteDefinition<string, T> | ExceptHandler<T> | readonly Route<T>[];
type NormalizedRouteDefinition<T extends RequestInfo = RequestInfo> = {
    path: string;
    handler: RouteHandler<T> | MethodHandlers<T>;
    layouts?: React.FC<LayoutProps<T>>[];
};
export type RouteDefinition<Path extends string = string, T extends RequestInfo = RequestInfo> = NormalizedRouteDefinition<T> & {
    readonly __rwPath?: Path;
};
type TrimTrailingSlash<S extends string> = S extends `${infer Head}/` ? TrimTrailingSlash<Head> : S;
type TrimLeadingSlash<S extends string> = S extends `/${infer Rest}` ? TrimLeadingSlash<Rest> : S;
type NormalizePrefix<Prefix extends string> = TrimTrailingSlash<TrimLeadingSlash<Prefix>> extends "" ? "" : `/${TrimTrailingSlash<TrimLeadingSlash<Prefix>>}`;
type NormalizePath<Path extends string> = TrimTrailingSlash<Path> extends "/" ? "/" : `/${TrimTrailingSlash<TrimLeadingSlash<Path>>}`;
type JoinPaths<Prefix extends string, Path extends string> = NormalizePrefix<Prefix> extends "" ? NormalizePath<Path> : Path extends "/" ? NormalizePrefix<Prefix> : `${NormalizePrefix<Prefix>}${NormalizePath<Path>}`;
type PrefixedRouteValue<Prefix extends string, Value> = Value extends RouteDefinition<infer Path, infer Req> ? RouteDefinition<JoinPaths<Prefix, Path>, Req> : Value extends ExceptHandler<any> ? Value : Value extends readonly Route<any>[] ? PrefixedRouteArray<Prefix, Value> : Value;
type PrefixedRouteArray<Prefix extends string, Routes extends readonly Route<any>[]> = Routes extends readonly [] ? [] : Routes extends readonly [infer Head, ...infer Tail] ? readonly [
    PrefixedRouteValue<Prefix, Head>,
    ...PrefixedRouteArray<Prefix, Tail extends readonly Route<any>[] ? Tail : []>
] : ReadonlyArray<PrefixedRouteValue<Prefix, Routes[number]>>;
export declare function matchPath<T extends RequestInfo = RequestInfo>(routePath: string, requestPath: string): T["params"] | null;
export declare function defineRoutes<T extends RequestInfo = RequestInfo>(routes: readonly Route<T>[]): {
    routes: Route<T>[];
    handle: ({ request, renderPage, getRequestInfo, onError, runWithRequestInfoOverrides, rscActionHandler, }: {
        request: Request;
        renderPage: (requestInfo: T, Page: React.FC, onError: (error: unknown) => void) => Promise<Response>;
        getRequestInfo: () => T;
        onError: (error: unknown) => void;
        runWithRequestInfoOverrides: <Result>(overrides: Partial<T>, fn: () => Promise<Result>) => Promise<Result>;
        rscActionHandler: (request: Request) => Promise<unknown>;
    }) => Response | Promise<Response>;
};
/**
 * Defines a route handler for a path pattern.
 *
 * Supports three types of path patterns:
 * - Static: /about, /contact
 * - Parameters: /users/:id, /posts/:postId/edit
 * - Wildcards: /files/\*, /api/\*\/download
 *
 * @example
 * // Static route
 * route("/about", () => <AboutPage />)
 *
 * @example
 * // Route with parameters
 * route("/users/:id", ({ params }) => {
 *   return <UserProfile userId={params.id} />
 * })
 *
 * @example
 * // Route with wildcards
 * route("/files/*", ({ params }) => {
 *   const filePath = params.$0
 *   return <FileViewer path={filePath} />
 * })
 *
 * @example
 * // Method-based routing
 * route("/api/users", {
 *   get: () => Response.json(users),
 *   post: ({ request }) => Response.json({ status: "created" }, { status: 201 }),
 *   delete: () => new Response(null, { status: 204 }),
 * })
 *
 * @example
 * // Route with middleware array
 * route("/admin", [isAuthenticated, isAdmin, () => <AdminDashboard />])
 */
export declare function route<Path extends string, T extends RequestInfo = RequestInfo>(path: Path, handler: RouteHandler<T> | MethodHandlers<T>): RouteDefinition<NormalizePath<Path>, T>;
/**
 * Defines a route handler for the root path "/".
 *
 * @example
 * // Homepage
 * index(() => <HomePage />)
 *
 * @example
 * // With middleware
 * index([logRequest, () => <HomePage />])
 */
export declare function index<T extends RequestInfo = RequestInfo>(handler: RouteHandler<T>): RouteDefinition<"/", T>;
/**
 * Defines an error handler that catches errors from routes, middleware, and RSC actions.
 *
 * @example
 * // Global error handler
 * except((error, requestInfo) => {
 *   console.error(error);
 *   return new Response("Internal Server Error", { status: 500 });
 * })
 *
 * @example
 * // Error handler that returns a React component
 * except((error) => {
 *   return <ErrorPage error={error} />;
 * })
 */
export declare function except<T extends RequestInfo = RequestInfo>(handler: (error: unknown, requestInfo: T) => MaybePromise<React.JSX.Element | Response | void>): ExceptHandler<T>;
export declare function prefix<Prefix extends string, T extends RequestInfo = RequestInfo, Routes extends readonly Route<T>[] = readonly Route<T>[]>(prefixPath: Prefix, routes: Routes): PrefixedRouteArray<Prefix, Routes>;
export declare const wrapHandlerToThrowResponses: <T extends RequestInfo = RequestInfo>(handler: RouteFunction<T> | RouteComponent<T>) => RouteHandler<T>;
/**
 * Wraps routes with a layout component.
 *
 * @example
 * // Define a layout component
 * function BlogLayout({ children }: { children?: React.ReactNode }) {
 *   return (
 *     <div>
 *       <nav>Blog Navigation</nav>
 *       <main>{children}</main>
 *     </div>
 *   )
 * }
 *
 * // Apply layout to routes
 * const blogRoutes = layout(BlogLayout, [
 *   route("/", () => <BlogIndex />),
 *   route("/post/:id", ({ params }) => <BlogPost id={params.id} />),
 * ])
 */
export declare function layout<TLayout extends RequestInfo = RequestInfo, Routes extends readonly Route<any>[] = readonly Route<any>[]>(LayoutComponent: React.FC<LayoutProps<TLayout>>, routes: Routes): Routes;
/**
 * Wraps routes with a Document component and configures rendering options.
 *
 * @param options.rscPayload - Toggle the RSC payload that's appended to the Document. Disabling this will mean that interactivity no longer works.
 * @param options.ssr - Disable sever side rendering for all these routes. This only allow client side rendering, which requires `rscPayload` to be enabled.
 *
 * @example
 * // Basic usage
 * defineApp([
 *   render(Document, [
 *     route("/", () => <HomePage />),
 *     route("/about", () => <AboutPage />),
 *   ]),
 * ])
 *
 * @example
 * // With custom rendering options
 * render(Document, [
 *   route("/", () => <HomePage />),
 * ], {
 *   rscPayload: true,
 *   ssr: true,
 * })
 */
type RenderedRoutes<T extends RequestInfo, Routes extends readonly Route<T>[]> = readonly [RouteMiddleware<T>, ...Routes];
export declare function render<T extends RequestInfo = RequestInfo, Routes extends readonly Route<T>[] = readonly Route<T>[]>(Document: React.FC<DocumentProps<T>>, routes: Routes, options?: {
    rscPayload?: boolean;
    ssr?: boolean;
}): RenderedRoutes<T, Routes>;
export declare const isClientReference: (value: any) => boolean;
export {};
