UNPKG

rwsdk

Version:

Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime

162 lines (161 loc) 6.01 kB
import React from "react"; import { RequestInfo } from "../requestInfo/types"; import type { DocumentProps, LayoutProps } from "./types.js"; export type RouteMiddleware<T extends RequestInfo = RequestInfo> = (requestInfo: T) => MaybePromise<React.JSX.Element | Response | void>; type RouteFunction<T extends RequestInfo = RequestInfo> = (requestInfo: T) => MaybePromise<Response>; type MaybePromise<T> = T | Promise<T>; type RouteComponent<T extends RequestInfo = RequestInfo> = (requestInfo: 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<T> | Array<Route<T>>; export type RouteDefinition<T extends RequestInfo = RequestInfo> = { path: string; handler: RouteHandler<T> | MethodHandlers<T>; layouts?: React.FC<LayoutProps<T>>[]; }; export declare function matchPath<T extends RequestInfo = RequestInfo>(routePath: string, requestPath: string): T["params"] | null; export declare function defineRoutes<T extends RequestInfo = RequestInfo>(routes: 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<T extends RequestInfo = RequestInfo>(path: string, handler: RouteHandler<T> | MethodHandlers<T>): RouteDefinition<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>; /** * Prefixes a group of routes with a path. * * @example * // Organize blog routes under /blog * const blogRoutes = [ * route("/", () => <BlogIndex />), * route("/post/:id", ({ params }) => <BlogPost id={params.id} />), * route("/admin", [isAuthenticated, () => <BlogAdmin />]), * ] * * // In worker.tsx * defineApp([ * render(Document, [ * route("/", () => <HomePage />), * prefix("/blog", blogRoutes), * ]), * ]) */ export declare function prefix<T extends RequestInfo = RequestInfo>(prefixPath: string, routes: Route<T>[]): Route<T>[]; 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<T extends RequestInfo = RequestInfo>(LayoutComponent: React.FC<LayoutProps<T>>, routes: Route<T>[]): Route<T>[]; /** * 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, * }) */ export declare function render<T extends RequestInfo = RequestInfo>(Document: React.FC<DocumentProps<T>>, routes: Route<T>[], options?: { rscPayload?: boolean; ssr?: boolean; }): Route<T>[]; export declare const isClientReference: (value: any) => boolean; export {};