UNPKG

alepha

Version:

Alepha is a convention-driven TypeScript framework for building robust, end-to-end type-safe applications, from serverless APIs to full-stack React apps.

748 lines (745 loc) 26.1 kB
import * as _alepha_core17 from "alepha"; import * as _alepha_core11 from "alepha"; import * as _alepha_core13 from "alepha"; import * as _alepha_core1 from "alepha"; import * as _alepha_core0 from "alepha"; import { Alepha, Async, Descriptor, KIND, Service, State, Static, TObject, TSchema } from "alepha"; import { ApiLinksResponse, RequestConfigSchema, ServerHandler, ServerRequest, ServerRouterProvider, ServerTimingProvider } from "alepha/server"; import { ServerRouteCache } from "alepha/server/cache"; import { ClientScope, HttpVirtualClient, LinkProvider, VirtualAction } from "alepha/server/links"; import * as react0$1 from "react"; import * as react0 from "react"; import * as react1 from "react"; import React, { AnchorHTMLAttributes, CSSProperties, ErrorInfo, FC, PropsWithChildren, ReactNode } from "react"; import * as react_jsx_runtime0$1 from "react/jsx-runtime"; import * as react_jsx_runtime0 from "react/jsx-runtime"; import * as react_jsx_runtime2 from "react/jsx-runtime"; import { Route, RouterProvider } from "alepha/router"; import { ServerStaticProvider } from "alepha/server/static"; import { Root } from "react-dom/client"; //#region src/components/ClientOnly.d.ts interface ClientOnlyProps { fallback?: ReactNode; disabled?: boolean; } /** * A small utility component that renders its children only on the client side. * * Optionally, you can provide a fallback React node that will be rendered. * * You should use this component when * - you have code that relies on browser-specific APIs * - you want to avoid server-side rendering for a specific part of your application * - you want to prevent pre-rendering of a component */ declare const ClientOnly: (props: PropsWithChildren<ClientOnlyProps>) => ReactNode; //#endregion //#region src/providers/BrowserRouterProvider.d.ts interface BrowserRoute extends Route { page: PageRoute; } declare class BrowserRouterProvider extends RouterProvider<BrowserRoute> { protected readonly log: _alepha_core17.Logger; protected readonly alepha: Alepha; protected readonly pageDescriptorProvider: PageDescriptorProvider; add(entry: PageRouteEntry): void; protected readonly configure: _alepha_core17.HookDescriptor<"configure">; transition(url: URL, options?: TransitionOptions): Promise<RouterRenderResult>; root(state: RouterState, context: PageReactContext): ReactNode; } //# sourceMappingURL=BrowserRouterProvider.d.ts.map //#endregion //#region src/providers/ReactBrowserProvider.d.ts declare class ReactBrowserProvider { protected readonly log: _alepha_core11.Logger; protected readonly client: LinkProvider; protected readonly alepha: Alepha; protected readonly router: BrowserRouterProvider; protected root: Root; transitioning?: { to: string; }; state: RouterState; get document(): Document; get history(): History; get location(): Location; get url(): string; pushState(url: string, replace?: boolean): void; invalidate(props?: Record<string, any>): Promise<void>; go(url: string, options?: RouterGoOptions): Promise<void>; protected render(options?: { url?: string; previous?: PreviousLayerData[]; }): Promise<RouterRenderResult>; /** * Get embedded layers from the server. */ protected getHydrationState(): ReactHydrationState | undefined; readonly ready: _alepha_core11.HookDescriptor<"ready">; } interface RouterGoOptions { replace?: boolean; match?: TransitionOptions; params?: Record<string, string>; query?: Record<string, string>; } interface ReactHydrationState { layers?: Array<PreviousLayerData>; links?: ApiLinksResponse; } //# sourceMappingURL=ReactBrowserProvider.d.ts.map //#endregion //#region src/hooks/RouterHookApi.d.ts declare class RouterHookApi<T extends object> { private readonly pages; private readonly context; private readonly state; private readonly layer; private readonly pageApi; private readonly browser?; constructor(pages: PageRoute[], context: PageReactContext, state: RouterState, layer: { path: string; }, pageApi: PageDescriptorProvider, browser?: ReactBrowserProvider | undefined); path(name: keyof VirtualRouter<T>, config?: { params?: Record<string, string>; query?: Record<string, string>; }): string; getURL(): URL; get location(): Location; get current(): RouterState; get pathname(): string; get query(): Record<string, string>; back(): Promise<void>; forward(): Promise<void>; invalidate(props?: Record<string, any>): Promise<void>; /** * Create a valid href for the given pathname. * * @param pathname * @param layer */ createHref(pathname: HrefLike, layer?: { path: string; }, options?: { params?: Record<string, any>; }): string; go(path: string, options?: RouterGoOptions): Promise<void>; go(path: keyof VirtualRouter<T>, options?: RouterGoOptions): Promise<void>; anchor(path: string, options?: { params?: Record<string, any>; }): AnchorProps; anchor(path: keyof VirtualRouter<T>, options?: { params?: Record<string, any>; }): AnchorProps; /** * Set query params. * * @param record * @param options */ setQueryParams(record: Record<string, any> | ((queryParams: Record<string, any>) => Record<string, any>), options?: { /** * If true, this will add a new entry to the history stack. */ push?: boolean; }): void; } type HrefLike = string | { options: { path?: string; name?: string; }; }; type VirtualRouter<T> = { [K in keyof T as T[K] extends PageDescriptor ? K : never]: T[K] }; //# sourceMappingURL=RouterHookApi.d.ts.map //#endregion //#region src/errors/Redirection.d.ts declare class Redirection extends Error { readonly page: HrefLike; constructor(page: HrefLike); } //# sourceMappingURL=Redirection.d.ts.map //#endregion //#region src/descriptors/$page.d.ts /** * Main descriptor for defining a React route in the application. */ declare const $page: { <TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = any, TPropsParent extends object = TPropsParentDefault>(options: PageDescriptorOptions<TConfig, TProps, TPropsParent>): PageDescriptor<TConfig, TProps, TPropsParent>; [KIND]: typeof PageDescriptor; }; interface PageDescriptorOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> { /** * Name your page. * * @default Descriptor key */ name?: string; /** * Optional description of the page. */ description?: string; /** * Add a pathname to the page. * * Pathname can contain parameters, like `/post/:slug`. * * @default "" */ path?: string; /** * Add an input schema to define: * - `params`: parameters from the pathname. * - `query`: query parameters from the URL. */ schema?: TConfig; /** * Load data before rendering the page. * * This function receives * - the request context and * - the parent props (if page has a parent) * * In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration. * * Resolve can be stopped by throwing an error, which will be handled by the `errorHandler` function. * It's common to throw a `NotFoundError` to display a 404 page. * * RedirectError can be thrown to redirect the user to another page. */ resolve?: (context: PageResolve<TConfig, TPropsParent>) => Async<TProps>; /** * The component to render when the page is loaded. * * If `lazy` is defined, this will be ignored. * Prefer using `lazy` to improve the initial loading time. */ component?: FC<TProps & TPropsParent>; /** * Lazy load the component when the page is loaded. * * It's recommended to use this for components to improve the initial loading time * and enable code-splitting. */ lazy?: () => Promise<{ default: FC<TProps & TPropsParent>; }>; /** * Set some children pages and make the page a parent page. * * /!\ Parent page can't be rendered directly. /!\ * * If you still want to render at this pathname, add a child page with an empty path. */ children?: Array<PageDescriptor> | (() => Array<PageDescriptor>); parent?: PageDescriptor<PageConfigSchema, TPropsParent>; can?: () => boolean; /** * Catch any error from the `resolve` function or during `rendering`. * * Expected to return one of the following: * - a ReactNode to render an error page * - a Redirection to redirect the user * - undefined to let the error propagate * * If not defined, the error will be thrown and handled by the server or client error handler. * If a leaf $page does not define an error handler, the error can be caught by parent pages. * * @example Catch a 404 from API and render a custom not found component: * ```ts * resolve: async ({ params, query }) => { * api.fetch("/api/resource", { params, query }); * }, * errorHandler: (error, context) => { * if (HttpError.is(error, 404)) { * return <ResourceNotFound />; * } * } * ``` * * @example Catch an 401 error and redirect the user to the login page: * ```ts * resolve: async ({ params, query }) => { * // but the user is not authenticated * api.fetch("/api/resource", { params, query }); * }, * errorHandler: (error, context) => { * if (HttpError.is(error, 401)) { * // throwing a Redirection is also valid! * return new Redirection("/login"); * } * } * ``` */ errorHandler?: ErrorHandler; /** * If true, the page will be considered as a static page, immutable and cacheable. * Replace boolean by an object to define static entries. (e.g. list of params/query) * * For now, it only works with `@alepha/vite` which can pre-render the page at build time. * * It will act as timeless cached page server-side. You can use `cache` to configure the cache behavior. */ static?: boolean | { entries?: Array<Partial<PageRequestConfig<TConfig>>>; }; cache?: ServerRouteCache; /** * If true, force the page to be rendered only on the client-side. * It uses the `<ClientOnly/>` component to render the page. */ client?: boolean | ClientOnlyProps; /** * Called before the server response is sent to the client. */ onServerResponse?: (request: ServerRequest) => any; /** * Called when user leaves the page. (browser only) */ onLeave?: () => void; } type ErrorHandler = (error: Error, context: PageReactContext) => ReactNode | Redirection | undefined; declare class PageDescriptor<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> extends Descriptor<PageDescriptorOptions<TConfig, TProps, TPropsParent>> { protected onInit(): void; get name(): string; /** * For testing or build purposes, this will render the page (with or without the HTML layout) and return the HTML and context. * Only valid for server-side rendering, it will throw an error if called on the client-side. */ render(options?: PageDescriptorRenderOptions): Promise<PageDescriptorRenderResult>; } interface PageConfigSchema { query?: TSchema; params?: TSchema; } type TPropsDefault = any; type TPropsParentDefault = {}; interface PageDescriptorRenderOptions { params?: Record<string, string>; query?: Record<string, string>; html?: boolean; hydration?: boolean; } interface PageDescriptorRenderResult { html: string; context: PageReactContext; } interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema> { params: TConfig["params"] extends TSchema ? Static<TConfig["params"]> : Record<string, string>; query: TConfig["query"] extends TSchema ? Static<TConfig["query"]> : Record<string, string>; } type PageResolve<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & PageReactContext; //# sourceMappingURL=$page.d.ts.map //#endregion //#region src/providers/PageDescriptorProvider.d.ts declare const envSchema$1: _alepha_core13.TObject<{ REACT_STRICT_MODE: _alepha_core13.TBoolean; }>; declare module "alepha" { interface Env extends Partial<Static<typeof envSchema$1>> {} } declare class PageDescriptorProvider { protected readonly log: _alepha_core13.Logger; protected readonly env: { REACT_STRICT_MODE: boolean; }; protected readonly alepha: Alepha; protected readonly pages: PageRoute[]; getPages(): PageRoute[]; page(name: string): PageRoute; pathname(name: string, options?: { params?: Record<string, string>; query?: Record<string, string>; }): string; url(name: string, options?: { params?: Record<string, string>; base?: string; }): URL; root(state: RouterState, context: PageReactContext): ReactNode; createLayers(route: PageRoute, request: PageRequest): Promise<CreateLayersResult>; protected createRedirectionLayer(href: HrefLike, context: { pathname: string; search: string; }): { layers: never[]; redirect: string; pathname: string; search: string; }; protected getErrorHandler(route: PageRoute): ErrorHandler | undefined; protected createElement(page: PageRoute, props: Record<string, any>): Promise<ReactNode>; renderError(error: Error): ReactNode; renderEmptyView(): ReactNode; href(page: { options: { name?: string; }; }, params?: Record<string, any>): string; compile(path: string, params?: Record<string, string>): string; protected renderView(index: number, path: string, view: ReactNode | undefined, page: PageRoute): ReactNode; protected readonly configure: _alepha_core13.HookDescriptor<"configure">; protected map(pages: Array<PageDescriptor>, target: PageDescriptor): PageRouteEntry; add(entry: PageRouteEntry): void; protected createMatch(page: PageRoute): string; protected _next: number; protected nextId(): string; } declare const isPageRoute: (it: any) => it is PageRoute; interface PageRouteEntry extends Omit<PageDescriptorOptions, "children" | "parent"> { children?: PageRouteEntry[]; } interface PageRoute extends PageRouteEntry { type: "page"; name: string; parent?: PageRoute; match: string; } interface Layer { config?: { query?: Record<string, any>; params?: Record<string, any>; context?: Record<string, any>; }; name: string; props?: Record<string, any>; error?: Error; part?: string; element: ReactNode; index: number; path: string; route?: PageRoute; cache?: boolean; } type PreviousLayerData = Omit<Layer, "element" | "index" | "path">; interface AnchorProps { href: string; onClick: (ev?: any) => any; } interface RouterState { pathname: string; search: string; layers: Array<Layer>; } interface TransitionOptions { state?: RouterState; previous?: PreviousLayerData[]; context?: PageReactContext; } interface RouterStackItem { route: PageRoute; config?: Record<string, any>; props?: Record<string, any>; error?: Error; cache?: boolean; } interface RouterRenderResult { state: RouterState; context: PageReactContext; redirect?: string; } interface PageRequest extends PageReactContext { params: Record<string, any>; query: Record<string, string>; previous?: PreviousLayerData[]; } interface CreateLayersResult extends RouterState { redirect?: string; } /** * It's like RouterState, but publicly available in React context. * This is where we store all plugin data! */ interface PageReactContext { url: URL; onError: ErrorHandler; links?: ApiLinksResponse; params: Record<string, any>; query: Record<string, string>; } //#endregion //#region src/components/ErrorBoundary.d.ts /** * Props for the ErrorBoundary component. */ interface ErrorBoundaryProps { /** * Fallback React node to render when an error is caught. * If not provided, a default error message will be shown. */ fallback: (error: Error) => ReactNode; /** * Optional callback that receives the error and error info. * Use this to log errors to a monitoring service. */ onError?: (error: Error, info: ErrorInfo) => void; } /** * State of the ErrorBoundary component. */ interface ErrorBoundaryState { error?: Error; } /** * A reusable error boundary for catching rendering errors * in any part of the React component tree. */ declare class ErrorBoundary extends React.Component<PropsWithChildren<ErrorBoundaryProps>, ErrorBoundaryState> { constructor(props: ErrorBoundaryProps); /** * Update state so the next render shows the fallback UI. */ static getDerivedStateFromError(error: Error): ErrorBoundaryState; /** * Lifecycle method called when an error is caught. * You can log the error or perform side effects here. */ componentDidCatch(error: Error, info: ErrorInfo): void; render(): ReactNode; } //#endregion //#region src/components/Link.d.ts interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> { to: string; children?: React.ReactNode; } declare const Link: (props: LinkProps) => react_jsx_runtime0$1.JSX.Element; //#endregion //#region src/components/NestedView.d.ts interface NestedViewProps { children?: ReactNode; } /** * A component that renders the current view of the nested router layer. * * To be simple, it renders the `element` of the current child page of a parent page. * * @example * ```tsx * import { NestedView } from "alepha/react"; * * class App { * parent = $page({ * component: () => <NestedView />, * }); * * child = $page({ * parent: this.root, * component: () => <div>Child Page</div>, * }); * } * ``` */ declare const NestedView: (props: NestedViewProps) => react_jsx_runtime0.JSX.Element; //#endregion //#region src/components/NotFound.d.ts declare function NotFoundPage(props: { style?: CSSProperties; }): react_jsx_runtime2.JSX.Element; //# sourceMappingURL=NotFound.d.ts.map //#endregion //#region src/contexts/AlephaContext.d.ts declare const AlephaContext: react0$1.Context<Alepha | undefined>; //# sourceMappingURL=AlephaContext.d.ts.map //#endregion //#region src/contexts/RouterContext.d.ts interface RouterContextValue { state: RouterState; context: PageReactContext; } declare const RouterContext: react0.Context<RouterContextValue | undefined>; //# sourceMappingURL=RouterContext.d.ts.map //#endregion //#region src/contexts/RouterLayerContext.d.ts interface RouterLayerContextValue { index: number; path: string; } declare const RouterLayerContext: react1.Context<RouterLayerContextValue | undefined>; //# sourceMappingURL=RouterLayerContext.d.ts.map //#endregion //#region src/hooks/useActive.d.ts declare const useActive: (path?: HrefLike) => UseActiveHook; interface UseActiveHook { isActive: boolean; anchorProps: AnchorProps; isPending: boolean; name?: string; } //# sourceMappingURL=useActive.d.ts.map //#endregion //#region src/hooks/useAlepha.d.ts declare const useAlepha: () => Alepha; //# sourceMappingURL=useAlepha.d.ts.map //#endregion //#region src/hooks/useClient.d.ts declare const useClient: <T extends object>(_scope?: ClientScope) => HttpVirtualClient<T>; //# sourceMappingURL=useClient.d.ts.map //#endregion //#region src/hooks/useInject.d.ts declare const useInject: <T extends object>(service: Service<T>) => T; //# sourceMappingURL=useInject.d.ts.map //#endregion //#region src/hooks/useQueryParams.d.ts interface UseQueryParamsHookOptions { format?: "base64" | "querystring"; key?: string; push?: boolean; } declare const useQueryParams: <T extends TObject>(schema: T, options?: UseQueryParamsHookOptions) => [Static<T>, (data: Static<T>) => void]; //# sourceMappingURL=useQueryParams.d.ts.map //#endregion //#region src/hooks/useRouter.d.ts declare const useRouter: <T extends object>() => RouterHookApi<T>; //# sourceMappingURL=useRouter.d.ts.map //#endregion //#region src/hooks/useRouterEvents.d.ts declare const useRouterEvents: (opts?: { onBegin?: (ev: { state: RouterState; }) => void; onEnd?: (ev: { state: RouterState; context: PageReactContext; }) => void; onError?: (ev: { state: RouterState; error: Error; }) => void; }, deps?: any[]) => void; //# sourceMappingURL=useRouterEvents.d.ts.map //#endregion //#region src/hooks/useRouterState.d.ts declare const useRouterState: () => RouterState; //# sourceMappingURL=useRouterState.d.ts.map //#endregion //#region src/hooks/useSchema.d.ts declare const useSchema: <TConfig extends RequestConfigSchema>(action: VirtualAction<TConfig>) => UseSchemaReturn<TConfig>; type UseSchemaReturn<TConfig extends RequestConfigSchema> = TConfig & { loading: boolean; }; /** * Get an action schema during server-side rendering (SSR) or client-side rendering (CSR). */ declare const ssrSchemaLoading: (alepha: Alepha, name: string) => RequestConfigSchema | { loading: boolean; }; //# sourceMappingURL=useSchema.d.ts.map //#endregion //#region src/hooks/useStore.d.ts /** * Hook to access and mutate the Alepha state. */ declare const useStore: <Key extends keyof State>(key: Key, defaultValue?: State[Key]) => [State[Key], (value: State[Key]) => void]; //# sourceMappingURL=useStore.d.ts.map //#endregion //#region src/providers/ReactServerProvider.d.ts declare const envSchema: _alepha_core1.TObject<{ REACT_SERVER_DIST: _alepha_core1.TString; REACT_SERVER_PREFIX: _alepha_core1.TString; REACT_SSR_ENABLED: _alepha_core1.TOptional<_alepha_core1.TBoolean>; REACT_ROOT_ID: _alepha_core1.TString; REACT_SERVER_TEMPLATE: _alepha_core1.TOptional<_alepha_core1.TString>; }>; declare module "alepha" { interface Env extends Partial<Static<typeof envSchema>> {} interface State { "react.server.ssr"?: boolean; } } declare class ReactServerProvider { protected readonly log: _alepha_core1.Logger; protected readonly alepha: Alepha; protected readonly pageDescriptorProvider: PageDescriptorProvider; protected readonly serverStaticProvider: ServerStaticProvider; protected readonly serverRouterProvider: ServerRouterProvider; protected readonly serverTimingProvider: ServerTimingProvider; protected readonly env: { REACT_SSR_ENABLED?: boolean | undefined; REACT_SERVER_TEMPLATE?: string | undefined; REACT_SERVER_DIST: string; REACT_SERVER_PREFIX: string; REACT_ROOT_ID: string; }; protected readonly ROOT_DIV_REGEX: RegExp; readonly onConfigure: _alepha_core1.HookDescriptor<"configure">; get template(): string; protected registerPages(templateLoader: TemplateLoader): Promise<void>; protected getPublicDirectory(): string; protected configureStaticServer(root: string): Promise<void>; protected configureVite(ssrEnabled: boolean): Promise<void>; /** * For testing purposes, creates a render function that can be used. */ protected createRenderFunction(name: string, withIndex?: boolean): (options?: PageDescriptorRenderOptions) => Promise<{ context: PageRequest; state: CreateLayersResult; html: string; } | { context: PageRequest; html: string; }>; protected createHandler(page: PageRoute, templateLoader: TemplateLoader): ServerHandler; renderToHtml(template: string, state: RouterState, context: PageReactContext, hydration?: boolean): string | Redirection; protected fillTemplate(response: { html: string; }, app: string, script: string): void; } type TemplateLoader = () => Promise<string | undefined>; //#endregion //#region src/index.d.ts declare module "alepha" { interface Hooks { "react:router:createLayers": { request: ServerRequest; context: PageRequest; layers: PageRequest[]; }; "react:server:render:begin": { request?: ServerRequest; context: PageRequest; }; "react:server:render:end": { request?: ServerRequest; context: PageRequest; state: RouterState; html: string; }; "react:browser:render": { state: RouterState; context: PageReactContext; hydration?: ReactHydrationState; }; "react:transition:begin": { state: RouterState; context: PageReactContext; }; "react:transition:success": { state: RouterState; context: PageReactContext; }; "react:transition:error": { error: Error; state: RouterState; context: PageReactContext; }; "react:transition:end": { state: RouterState; context: PageReactContext; }; } } /** * Provides full-stack React development with declarative routing, server-side rendering, and client-side hydration. * * The React module enables building modern React applications using the `$page` descriptor on class properties. * It delivers seamless server-side rendering, automatic code splitting, and client-side navigation with full * type safety and schema validation for route parameters and data. * * @see {@link $page} * @module alepha.react */ declare const AlephaReact: _alepha_core0.Service<_alepha_core0.Module>; //# sourceMappingURL=index.d.ts.map //#endregion export { $page, AlephaContext, AlephaReact, AnchorProps, ClientOnly, CreateLayersResult, ErrorBoundary, ErrorHandler, HrefLike, Layer, Link, LinkProps, NestedView, NotFoundPage as NotFound, PageConfigSchema, PageDescriptor, PageDescriptorOptions, PageDescriptorProvider, PageDescriptorRenderOptions, PageDescriptorRenderResult, PageReactContext, PageRequest, PageRequestConfig, PageResolve, PageRoute, PageRouteEntry, PreviousLayerData, ReactBrowserProvider, ReactHydrationState, ReactServerProvider, Redirection, RouterContext, RouterContextValue, RouterGoOptions, RouterHookApi, RouterLayerContext, RouterLayerContextValue, RouterRenderResult, RouterStackItem, RouterState, TPropsDefault, TPropsParentDefault, TransitionOptions, UseActiveHook, UseQueryParamsHookOptions, UseSchemaReturn, VirtualRouter, isPageRoute, ssrSchemaLoading, useActive, useAlepha, useClient, useInject, useQueryParams, useRouter, useRouterEvents, useRouterState, useSchema, useStore }; //# sourceMappingURL=index.d.ts.map