UNPKG

next

Version:

The React Framework

195 lines (194 loc) 7.26 kB
/** * App Router types - Client-safe types for the Next.js App Router * * This file contains type definitions that can be safely imported * by both client-side and server-side code without circular dependencies. */ import type React from 'react'; export type LoadingModuleData = [React.JSX.Element, React.ReactNode, React.ReactNode] | null; /** viewport metadata node */ export type HeadData = React.ReactNode; export type ChildSegmentMap = Map<string, CacheNode>; /** * Cache node used in app-router / layout-router. */ export type CacheNode = { /** * When rsc is not null, it represents the RSC data for the * corresponding segment. * * `null` is a valid React Node but because segment data is always a * <LayoutRouter> component, we can use `null` to represent empty. When it is * null, it represents missing data, and rendering should suspend. */ rsc: React.ReactNode; /** * Represents a static version of the segment that can be shown immediately, * and may or may not contain dynamic holes. It's prefetched before a * navigation occurs. * * During rendering, we will choose whether to render `rsc` or `prefetchRsc` * with `useDeferredValue`. As with the `rsc` field, a value of `null` means * no value was provided. In this case, the LayoutRouter will go straight to * rendering the `rsc` value; if that one is also missing, it will suspend and * trigger a lazy fetch. */ prefetchRsc: React.ReactNode; prefetchHead: HeadData | null; head: HeadData; loading: LoadingModuleData | Promise<LoadingModuleData>; parallelRoutes: Map<string, ChildSegmentMap>; /** * The timestamp of the navigation that last updated the CacheNode's data. If * a CacheNode is reused from a previous navigation, this value is not * updated. Used to track the staleness of the data. */ navigatedAt: number; }; export type DynamicParamTypes = 'catchall' | 'catchall-intercepted-(..)(..)' | 'catchall-intercepted-(.)' | 'catchall-intercepted-(..)' | 'catchall-intercepted-(...)' | 'optional-catchall' | 'dynamic' | 'dynamic-intercepted-(..)(..)' | 'dynamic-intercepted-(.)' | 'dynamic-intercepted-(..)' | 'dynamic-intercepted-(...)'; export type DynamicParamTypesShort = 'c' | 'ci(..)(..)' | 'ci(.)' | 'ci(..)' | 'ci(...)' | 'oc' | 'd' | 'di(..)(..)' | 'di(.)' | 'di(..)' | 'di(...)'; export type Segment = string | [ paramName: string, paramCacheKey: string, dynamicParamType: DynamicParamTypesShort ]; /** * Router state */ export type FlightRouterState = [ segment: Segment, parallelRoutes: { [parallelRouterKey: string]: FlightRouterState; }, url?: string | null, /** * "refresh" and "refetch", despite being similarly named, have different * semantics: * - "refetch" is used during a request to inform the server where rendering * should start from. * * - "refresh" is used by the client to mark that a segment should re-fetch the * data from the server for the current segment. It uses the "url" property * above to determine where to fetch from. * * - "inside-shared-layout" is used during a prefetch request to inform the * server that even if the segment matches, it should be treated as if it's * within the "new" part of a navigation — inside the shared layout. If * the segment doesn't match, then it has no effect, since it would be * treated as new regardless. If it does match, though, the server does not * need to render it, because the client already has it. * * - "metadata-only" instructs the server to skip rendering the segments and * only send the head data. * * A bit confusing, but that's because it has only one extremely narrow use * case — during a non-PPR prefetch, the server uses it to find the first * loading boundary beneath a shared layout. * * TODO: We should rethink the protocol for dynamic requests. It might not * make sense for the client to send a FlightRouterState, since this type is * overloaded with concerns. */ refresh?: 'refetch' | 'refresh' | 'inside-shared-layout' | 'metadata-only' | null, isRootLayout?: boolean, /** * Only present when responding to a tree prefetch request. Indicates whether * there is a loading boundary somewhere in the tree. The client cache uses * this to determine if it can skip the data prefetch request. */ hasLoadingBoundary?: HasLoadingBoundary ]; export declare const enum HasLoadingBoundary { SegmentHasLoadingBoundary = 1, SubtreeHasLoadingBoundary = 2, SubtreeHasNoLoadingBoundary = 3 } /** * Individual Flight response path */ export type FlightSegmentPath = any[] | [ segment: Segment, parallelRouterKey: string, segment: Segment, parallelRouterKey: string, segment: Segment, parallelRouterKey: string ]; /** * Represents a tree of segments and the Flight data (i.e. React nodes) that * correspond to each one. The tree is isomorphic to the FlightRouterState; * however in the future we want to be able to fetch arbitrary partial segments * without having to fetch all its children. So this response format will * likely change. */ export type CacheNodeSeedData = [ node: React.ReactNode | null, parallelRoutes: { [parallelRouterKey: string]: CacheNodeSeedData | null; }, loading: LoadingModuleData | Promise<LoadingModuleData>, isPartial: boolean, /** TODO: this doesn't feel like it belongs here, because it's only used during build, in `collectSegmentData` */ hasRuntimePrefetch: boolean ]; export type FlightDataSegment = [ Segment, FlightRouterState, CacheNodeSeedData | null, HeadData, boolean ]; export type FlightDataPath = any[] | [ ...FlightSegmentPath[], ...FlightDataSegment ]; /** * The Flight response data */ export type FlightData = Array<FlightDataPath> | string; export type ActionResult = Promise<any>; export type InitialRSCPayload = { /** buildId */ b: string; /** initialCanonicalUrlParts */ c: string[]; /** initialRenderedSearch */ q: string; /** couldBeIntercepted */ i: boolean; /** initialFlightData */ f: FlightDataPath[]; /** missingSlots */ m: Set<string> | undefined; /** GlobalError */ G: [React.ComponentType<any>, React.ReactNode | undefined]; /** prerendered */ S: boolean; }; export type NavigationFlightResponse = { /** buildId */ b: string; /** flightData */ f: FlightData; /** prerendered */ S: boolean; /** renderedSearch */ q: string; /** couldBeIntercepted */ i: boolean; /** runtimePrefetch - [isPartial, staleTime]. Only present in runtime prefetch responses. */ rp?: [boolean, number]; }; export type ActionFlightResponse = { /** actionResult */ a: ActionResult; /** buildId */ b: string; /** flightData */ f: FlightData; /** renderedSearch */ q: string; /** couldBeIntercepted */ i: boolean; }; export type RSCPayload = InitialRSCPayload | NavigationFlightResponse | ActionFlightResponse;