/**
 * Django-inspired URL patterns for @rangojs/router
 *
 * This module provides `urls()` and `path()` for defining routes with
 * URL patterns visible at the definition site.
 *
 * @example
 * ```typescript
 * // urls/blog.ts
 * export const blogPatterns = urls(({ path, layout, loader }) => [
 *   layout(BlogLayout, () => [
 *     path("/", BlogIndex, { name: "index" }),
 *     path("/:slug", BlogPost, { name: "post" }, () => [
 *       loader(PostLoader),
 *     ]),
 *   ]),
 * ]);
 *
 * // urls/index.ts
 * export const urlpatterns = urls(({ path, layout, include }) => [
 *   layout(RootLayout, () => [
 *     path("/", HomePage, { name: "home" }),
 *     include("/blog", blogPatterns, { name: "blog" }),
 *   ]),
 * ]);
 * ```
 */
import type { ReactNode } from "react";
import type { DefaultEnv, ErrorBoundaryHandler, ExtractParams, Handler, HandlerContext, LoaderDefinition, MiddlewareFn, NotFoundBoundaryHandler, PartialCacheOptions, RouterEnv, ShouldRevalidateFn, TrailingSlashMode } from "./types.js";
import type { CookieOptions } from "./router/middleware.js";
import type { AllUseItems, TypedLayoutItem, TypedRouteItem, ParallelItem, InterceptItem, MiddlewareItem, RevalidateItem, LoaderItem, LoadingItem, ErrorBoundaryItem, NotFoundBoundaryItem, LayoutUseItem, RouteUseItem, ResponseRouteUseItem, ParallelUseItem, InterceptUseItem, LoaderUseItem, WhenItem, TypedCacheItem, TypedIncludeItem, UrlPatternsBrand } from "./route-types.js";
import { type InterceptWhenFn } from "./server/context";
import { type PrerenderHandlerDefinition } from "./prerender.js";
import { type StaticHandlerDefinition } from "./static-handler.js";
import type { SearchSchema } from "./search-params.js";
/**
 * Symbol marking a route as a response route (non-RSC).
 * Stored on PathOptions and UrlPatterns to signal the trie to short-circuit.
 */
export declare const RESPONSE_TYPE: unique symbol;
/**
 * Handler that must return Response (not ReactNode).
 * Used by path.image(), path.stream(), path.any() (binary/streaming data).
 */
export type ResponseHandler<TParams = Record<string, string>, TEnv = any> = (ctx: ResponseHandlerContext<TParams, TEnv>) => Response | Promise<Response>;
/**
 * JSON-serializable value type for auto-wrap support.
 */
export type JsonValue = string | number | boolean | null | JsonValue[] | {
    [key: string]: JsonValue;
};
/**
 * Handler for JSON response routes.
 * Can return a plain JSON-serializable value (auto-wrapped) or Response (pass-through).
 */
export type JsonResponseHandler<TParams = Record<string, string>, TEnv = any> = (ctx: ResponseHandlerContext<TParams, TEnv>) => JsonValue | Response | Promise<JsonValue | Response>;
/**
 * Handler for text-based response routes (text, html, xml).
 * Can return a string (auto-wrapped) or Response (pass-through).
 */
export type TextResponseHandler<TParams = Record<string, string>, TEnv = any> = (ctx: ResponseHandlerContext<TParams, TEnv>) => string | Response | Promise<string | Response>;
/**
 * Lighter handler context for response routes.
 * No ctx.use() (no loaders). Supports setting response headers and cookies
 * without constructing a full Response object.
 */
export interface ResponseHandlerContext<TParams = Record<string, string>, TEnv = any> {
    request: Request;
    params: TParams;
    /** @internal Phantom property for params type invariance. Prevents mounting handlers on wrong routes. */
    readonly _paramCheck?: (params: TParams) => TParams;
    /** Platform bindings (DB, KV, secrets, etc.) extracted from RouterEnv. */
    env: TEnv extends RouterEnv<infer B, any> ? B : {};
    /** Query parameters from the URL (system params like `_rsc*` are filtered). */
    searchParams: URLSearchParams;
    /** The full URL object (with system params filtered). */
    url: URL;
    /** The pathname portion of the request URL. */
    pathname: string;
    reverse: (name: string, params?: Record<string, string>) => string;
    /** Read a variable set by middleware via ctx.set(key, value). */
    get: (key: string) => unknown;
    /** Set a response header. Merged into the auto-wrapped or pass-through Response. */
    header: (name: string, value: string) => void;
    /** Set a cookie on the response. */
    setCookie: (name: string, value: string, options?: CookieOptions) => void;
}
/**
 * Sentinel type for unnamed routes.
 * Using a branded string instead of `never` prevents TypeScript from
 * widening array type inference when mixing named and unnamed routes.
 */
export type UnnamedRoute = "$unnamed";
/**
 * Options for path() function
 */
export interface PathOptions<TName extends string = string, TSearch extends SearchSchema = {}> {
    /** Route name for href() lookups */
    name?: TName;
    /** Search param schema for typed query parameters */
    search?: TSearch;
    /** Trailing slash behavior: "never" (redirect /path/ to /path), "always" (redirect /path to /path/), "ignore" (match both) */
    trailingSlash?: TrailingSlashMode;
    /** Response type marker (set by path.json(), etc.) */
    [RESPONSE_TYPE]?: string;
}
/**
 * Internal representation of a URL pattern definition
 */
export interface PathDefinition {
    pattern: string;
    name?: string;
    handler: ReactNode | Handler<any, any, any>;
    use?: RouteUseItem[];
}
/**
 * Result of urls() - contains the route definitions
 */
export interface UrlPatterns<TEnv = any, TRoutes extends Record<string, any> = Record<string, string>, TResponses extends Record<string, unknown> = Record<string, unknown>> {
    /** Internal: route definitions */
    readonly definitions: PathDefinition[];
    /** Internal: compiled handler function */
    readonly handler: () => AllUseItems[];
    /** Internal: trailing slash config per route name */
    readonly trailingSlash: Record<string, TrailingSlashMode>;
    /** Brand for type checking */
    readonly [UrlPatternsBrand]: void;
    /** Environment type brand (phantom) */
    readonly _env?: TEnv;
    /** Routes type brand (phantom) - carries route name -> pattern mapping */
    readonly _routes?: TRoutes;
    /** Responses type brand (phantom) - carries route name -> response data type mapping */
    readonly _responses?: TResponses;
}
/**
 * Options for include()
 */
export interface IncludeOptions<TNamePrefix extends string = string> {
    /** Name prefix for all routes in this pattern set */
    name?: TNamePrefix;
}
/**
 * Prefix route names with a given prefix (e.g., "blog" + "post" = "blog.post")
 *
 * Filters out plain `string` index signatures to prevent dynamically-generated
 * routes from poisoning the route map. When TypeScript encounters very large
 * route sets (5000+ routes via Array.from), it may give up computing specific
 * types and fall back to Record<string, string>. Without filtering, PrefixRoutes
 * would map `string` to `${prefix}.${string}`, creating an index signature that
 * accepts ANY prefixed name and defeats type-safe route checking.
 *
 * Uses `string extends K` (conservative filter):
 * - Drops `string` keys (TypeScript fallback) -> prevents `[x: `site.${string}`]`
 * - Keeps template literal patterns like `item${number}` from Array.from loops,
 *   which are imprecise but still allow writing paths like `/shop/product/1`
 *
 * A more aggressive alternative (`{} extends Record<K, 1>`) would also drop
 * template literal patterns. We chose conservative because loop-generated routes
 * with `${number}` patterns still provide some value: they don't appear in
 * named-routes.gen.ts or IDE autocomplete, but they do let you manually write
 * valid paths without type errors.
 */
type PrefixRoutes<TRoutes extends Record<string, any>, TPrefix extends string> = TPrefix extends "" ? TRoutes : {
    [K in keyof TRoutes as K extends string ? string extends K ? never : `${TPrefix}.${K}` : never]: TRoutes[K];
};
/**
 * Prefix route patterns with a URL prefix (e.g., "/blog" + "/:slug" = "/blog/:slug")
 */
type PrefixPatterns<TRoutes extends Record<string, any>, TUrlPrefix extends string> = {
    [K in keyof TRoutes]: TRoutes[K] extends string ? `${TUrlPrefix}${TRoutes[K]}` : TRoutes[K] extends {
        readonly path: infer P extends string;
        readonly search: infer S;
    } ? {
        readonly path: `${TUrlPrefix}${P}`;
        readonly search: S;
    } : TRoutes[K];
};
/**
 * Convert a union type to an intersection type.
 * Used to combine route maps from multiple siblings without recursive tuple processing.
 */
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
/**
 * Extract routes from a single item (path, include, layout, cache with children)
 * D is the current depth level for nested layouts/caches
 */
type ExtractRoutesFromItem<T, D extends number = 40> = [D] extends [never] ? {} : T extends TypedRouteItem<infer TName, infer TPattern, any, infer TSearch> ? TName extends string ? TName extends UnnamedRoute ? {} : {} extends TSearch ? {
    [K in TName]: TPattern;
} : {
    [K in TName]: {
        readonly path: TPattern;
        readonly search: TSearch;
    };
} : {} : T extends TypedIncludeItem<infer TRoutes, infer TNamePrefix, infer TUrlPrefix> ? TNamePrefix extends string ? TUrlPrefix extends string ? PrefixRoutes<PrefixPatterns<TRoutes, TUrlPrefix>, TNamePrefix> : PrefixRoutes<TRoutes, TNamePrefix> : TUrlPrefix extends string ? PrefixPatterns<TRoutes, TUrlPrefix> : TRoutes : T extends TypedLayoutItem<infer TChildRoutes> ? TChildRoutes : T extends TypedCacheItem<infer TChildRoutes> ? TChildRoutes : {};
/**
 * Extract routes from an array of items using mapped types.
 * Uses UnionToIntersection to combine routes without recursive tuple processing,
 * removing the sibling limit that was caused by TypeScript recursion limits.
 * D is passed to ExtractRoutesFromItem for nested depth tracking.
 */
type ExtractRoutesFromItems<T extends readonly any[], D extends number = 40> = T extends readonly any[] ? UnionToIntersection<{
    [K in keyof T]: ExtractRoutesFromItem<T[K], D>;
}[number]> extends infer R ? R extends Record<string, any> ? R : {} : {} : {};
/**
 * Main utility: extract route map from urls() callback return type
 * Uses mapped types for sibling processing (no sibling limit).
 * Uses Simplify to force eager evaluation for interface extension compatibility.
 */
export type ExtractRoutes<T extends readonly any[]> = ExtractRoutesFromItems<T, 40>;
/**
 * Prefix keys of a Record<string, unknown> with a dot-separated prefix.
 * Used for response type maps through include().
 * Same index signature filter as PrefixRoutes (see comment there).
 */
type PrefixKeys<T extends Record<string, unknown>, TPrefix extends string> = TPrefix extends "" ? T : {
    [K in keyof T as K extends string ? string extends K ? never : `${TPrefix}.${K}` : never]: T[K];
};
/**
 * Extract response data types from a single item.
 * Parallel to ExtractRoutesFromItem but extracts name -> TData mapping.
 */
type ExtractResponsesFromItem<T, D extends number = 40> = [D] extends [never] ? {} : T extends TypedRouteItem<infer TName, any, infer TData> ? TName extends string ? TName extends UnnamedRoute ? {} : {
    [K in TName]: TData;
} : {} : T extends TypedIncludeItem<any, infer TNamePrefix, any, infer TResponses> ? TNamePrefix extends string ? TResponses extends Record<string, unknown> ? PrefixKeys<TResponses, TNamePrefix> : {} : TResponses extends Record<string, unknown> ? TResponses : {} : T extends TypedLayoutItem<any, infer TChildResponses> ? TChildResponses extends Record<string, unknown> ? TChildResponses : {} : T extends TypedCacheItem<any, infer TChildResponses> ? TChildResponses extends Record<string, unknown> ? TChildResponses : {} : {};
/**
 * Extract responses from an array of items using mapped types.
 * Parallel to ExtractRoutesFromItems.
 */
type ExtractResponsesFromItems<T extends readonly any[], D extends number = 40> = T extends readonly any[] ? UnionToIntersection<{
    [K in keyof T]: ExtractResponsesFromItem<T[K], D>;
}[number]> extends infer R ? R extends Record<string, unknown> ? R : {} : {} : {};
/**
 * Main utility: extract response data type map from urls() callback return type.
 * Parallel to ExtractRoutes.
 */
export type ExtractResponses<T extends readonly any[]> = ExtractResponsesFromItems<T, 40>;
/**
 * Helpers provided by urls()
 */
/**
 * Base path function signature for defining routes with URL patterns.
 */
export type PathFn<TEnv> = <const TPattern extends string, const TName extends string = UnnamedRoute, const TSearch extends SearchSchema = {}, TParams extends Record<string, any> = ExtractParams<TPattern>>(pattern: TPattern, handler: ReactNode | ((ctx: HandlerContext<TParams, TEnv, TSearch>) => ReactNode | Promise<ReactNode> | Response | Promise<Response>) | PrerenderHandlerDefinition<TParams> | StaticHandlerDefinition<TParams>, optionsOrUse?: PathOptions<TName, TSearch> | (() => RouteUseItem[]), use?: () => RouteUseItem[]) => string extends keyof TParams ? TypedRouteItem<TName, TPattern, unknown, TSearch> : ExtractParams<TPattern> extends TParams ? TParams extends ExtractParams<TPattern> ? TypedRouteItem<TName, TPattern, unknown, TSearch> : {
    __error: `Handler params do not match pattern "${TPattern}"`;
} : {
    __error: `Handler params do not match pattern "${TPattern}"`;
};
/**
 * Path function for response routes that must return Response (image, stream, any).
 * Handler must return Response, not ReactNode. Uses lighter ResponseHandlerContext.
 * Use items restricted to middleware() and cache() only.
 */
export type ResponsePathFn<TEnv> = <const TPattern extends string, const TName extends string = UnnamedRoute, const TSearch extends SearchSchema = {}>(pattern: TPattern, handler: ResponseHandler<ExtractParams<TPattern>, TEnv>, optionsOrUse?: PathOptions<TName, TSearch> | (() => ResponseRouteUseItem[]), use?: () => ResponseRouteUseItem[]) => TypedRouteItem<TName, TPattern, unknown, TSearch>;
/**
 * Path function for JSON response routes (path.json()).
 * Handler can return plain JSON-serializable values or Response.
 * TData is inferred from the handler's return type (excluding Response/Promise wrappers).
 */
export type JsonResponsePathFn<TEnv> = <const TPattern extends string, const TName extends string = UnnamedRoute, const TSearch extends SearchSchema = {}, TData = unknown>(pattern: TPattern, handler: (ctx: ResponseHandlerContext<ExtractParams<TPattern>, TEnv>) => TData | Response | Promise<TData | Response>, optionsOrUse?: PathOptions<TName, TSearch> | (() => ResponseRouteUseItem[]), use?: () => ResponseRouteUseItem[]) => TypedRouteItem<TName, TPattern, TData, TSearch>;
/**
 * Path function for text-based response routes (path.text(), path.html(), path.xml()).
 * Handler can return a string or Response. TData is always `string`.
 */
export type TextResponsePathFn<TEnv> = <const TPattern extends string, const TName extends string = UnnamedRoute, const TSearch extends SearchSchema = {}>(pattern: TPattern, handler: TextResponseHandler<ExtractParams<TPattern>, TEnv>, optionsOrUse?: PathOptions<TName, TSearch> | (() => ResponseRouteUseItem[]), use?: () => ResponseRouteUseItem[]) => TypedRouteItem<TName, TPattern, string, TSearch>;
/**
 * Base include function signature.
 */
export type IncludeFn<TEnv> = <TRoutes extends Record<string, any>, const TUrlPrefix extends string, const TNamePrefix extends string = never, TResponses extends Record<string, unknown> = Record<string, unknown>>(prefix: TUrlPrefix, patterns: UrlPatterns<TEnv, TRoutes, TResponses>, options?: IncludeOptions<TNamePrefix>) => TypedIncludeItem<TRoutes, TNamePrefix, TUrlPrefix, TResponses>;
export type PathHelpers<TEnv> = {
    /**
     * Define a route with URL pattern at definition site
     *
     * @example
     * ```typescript
     * // Pattern and component only
     * path("/about", AboutPage)
     *
     * // With options
     * path("/:slug", PostPage, { name: "post" })
     *
     * // With children (loaders, middleware, etc.)
     * path("/:slug", PostPage, { name: "post" }, () => [
     *   loader(PostLoader),
     * ])
     * ```
     */
    path: PathFn<TEnv> & {
        json: JsonResponsePathFn<TEnv>;
        text: TextResponsePathFn<TEnv>;
        html: TextResponsePathFn<TEnv>;
        xml: TextResponsePathFn<TEnv>;
        md: TextResponsePathFn<TEnv>;
        image: ResponsePathFn<TEnv>;
        stream: ResponsePathFn<TEnv>;
        any: ResponsePathFn<TEnv>;
    };
    /**
     * Define a layout that wraps child routes
     */
    layout: {
        (component: ReactNode | Handler<any, any, TEnv> | StaticHandlerDefinition): TypedLayoutItem<{}, {}>;
        <const TChildren extends readonly LayoutUseItem[]>(component: ReactNode | Handler<any, any, TEnv> | StaticHandlerDefinition, use: () => TChildren): TypedLayoutItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
    };
    /**
     * Include nested URL patterns with optional name prefix
     *
     * ```typescript
     * // Without name - routes keep local names
     * include("/blog", blogPatterns)
     *
     * // With name - routes are prefixed (e.g., "index" → "blog.index")
     * include("/blog", blogPatterns, { name: "blog" })
     * ```
     */
    include: IncludeFn<TEnv>;
    /**
     * Define parallel routes that render simultaneously in named slots
     */
    parallel: <TSlots extends Record<`@${string}`, Handler<any, any, TEnv> | ReactNode | StaticHandlerDefinition>>(slots: TSlots, use?: () => ParallelUseItem[]) => ParallelItem;
    /**
     * Define an intercepting route for soft navigation
     * Note: routeName must match a named path() in this urlpatterns
     */
    intercept: (slotName: `@${string}`, routeName: string, handler: ReactNode | Handler<any, any, TEnv>, use?: () => InterceptUseItem[]) => InterceptItem;
    /**
     * Attach middleware to the current route/layout
     */
    middleware: (...fns: MiddlewareFn<TEnv>[]) => MiddlewareItem;
    /**
     * Control when a segment should revalidate during navigation
     */
    revalidate: (fn: ShouldRevalidateFn<any, TEnv>) => RevalidateItem;
    /**
     * Attach a data loader to the current route/layout
     */
    loader: <TData>(loaderDef: LoaderDefinition<TData>, use?: () => LoaderUseItem[]) => LoaderItem;
    /**
     * Attach a loading component to the current route/layout
     */
    loading: (component: ReactNode, options?: {
        ssr?: boolean;
    }) => LoadingItem;
    /**
     * Attach an error boundary to catch errors in this segment
     */
    errorBoundary: (fallback: ReactNode | ErrorBoundaryHandler) => ErrorBoundaryItem;
    /**
     * Attach a not-found boundary to handle notFound() calls
     */
    notFoundBoundary: (fallback: ReactNode | NotFoundBoundaryHandler) => NotFoundBoundaryItem;
    /**
     * Define a condition for when an intercept should activate
     */
    when: (fn: InterceptWhenFn) => WhenItem;
    /**
     * Define cache configuration for segments
     */
    cache: {
        (): TypedCacheItem<{}, {}>;
        <const TChildren extends readonly AllUseItems[]>(children: () => TChildren): TypedCacheItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
        (options: PartialCacheOptions | false): TypedCacheItem<{}, {}>;
        <const TChildren extends readonly AllUseItems[]>(options: PartialCacheOptions | false, use: () => TChildren): TypedCacheItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
    };
};
/**
 * Define URL patterns with Django-inspired syntax
 *
 * Replaces map() as the entry point for route definitions.
 * URL patterns are now visible at the definition site via path().
 *
 * @example
 * ```typescript
 * export const blogPatterns = urls(({ path, layout, loader }) => [
 *   layout(BlogLayout, () => [
 *     path("/", BlogIndex, { name: "index" }),
 *     path("/:slug", BlogPost, { name: "post" }, () => [
 *       loader(PostLoader),
 *     ]),
 *   ]),
 * ]);
 * ```
 */
export declare function urls<TEnv = DefaultEnv, const TItems extends readonly AllUseItems[] = readonly AllUseItems[]>(builder: (helpers: PathHelpers<TEnv>) => TItems): UrlPatterns<TEnv, ExtractRoutes<TItems>, ExtractResponses<TItems>>;
/**
 * Extract route names from a UrlPatterns result
 * Used for type-safe href() generation
 */
export type ExtractRouteNames<T extends UrlPatterns<any>> = T extends UrlPatterns<infer _TEnv> ? string : never;
/**
 * Extract params for a specific route name
 */
export type ExtractPathParams<T extends UrlPatterns<any>, K extends string> = ExtractParams<string>;
/**
 * Error shape returned in the `{ error }` side of a JSON response envelope.
 */
export interface ResponseError {
    message: string;
    code?: string;
    type?: string;
    stack?: string;
}
/**
 * Discriminated union envelope for JSON response routes.
 * Consumers check `result.error` to discriminate between success and failure.
 *
 * @example
 * ```typescript
 * const result: ResponseEnvelope<Product> = await fetch(url).then(r => r.json());
 * if (result.error) {
 *   console.log(result.error.message, result.error.code);
 *   return;
 * }
 * result.data.name // fully typed
 * ```
 */
export type ResponseEnvelope<T> = {
    data: T;
    error?: undefined;
} | {
    data?: undefined;
    error: ResponseError;
};
/**
 * Extract the response data type for a named route from a UrlPatterns instance.
 * Wraps in ResponseEnvelope since JSON response routes return enveloped data.
 *
 * @example
 * ```typescript
 * const apiPatterns = urls(({ path }) => [
 *   path.json("/health", (ctx) => ({ status: "ok", timestamp: Date.now() }), { name: "health" }),
 * ]);
 *
 * type HealthData = RouteResponse<typeof apiPatterns, "health">;
 * // ResponseEnvelope<{ status: string; timestamp: number }>
 * ```
 */
export type RouteResponse<TPatterns, TName extends string> = TPatterns extends {
    readonly _responses?: infer R;
} ? TName extends keyof R ? ResponseEnvelope<Exclude<R[TName], Response>> : never : never;
export type { AllUseItems, IncludeItem, TypedRouteItem, TypedIncludeItem, TypedLayoutItem, TypedCacheItem, } from "./route-types.js";
//# sourceMappingURL=urls.d.ts.map