@remix-run/server-runtime
Version:
Server runtime for Remix
212 lines (211 loc) • 7.45 kB
TypeScript
import type { ActionFunction as RRActionFunction, ActionFunctionArgs as RRActionFunctionArgs, AgnosticRouteMatch, LoaderFunction as RRLoaderFunction, LoaderFunctionArgs as RRLoaderFunctionArgs, Location, Params } from "@remix-run/router";
import type { AppData, AppLoadContext } from "./data";
import type { LinkDescriptor } from "./links";
import type { SerializeFrom } from "./serialize";
export interface RouteModules<RouteModule> {
[routeId: string]: RouteModule | undefined;
}
/**
* @deprecated Use `LoaderFunctionArgs`/`ActionFunctionArgs` instead
*/
export type DataFunctionArgs = RRActionFunctionArgs<AppLoadContext> & RRLoaderFunctionArgs<AppLoadContext> & {
context: AppLoadContext;
};
/**
* A function that handles data mutations for a route on the server
*/
export type ActionFunction = (args: ActionFunctionArgs) => ReturnType<RRActionFunction>;
/**
* Arguments passed to a route `action` function
*/
export type ActionFunctionArgs = RRActionFunctionArgs<AppLoadContext> & {
context: AppLoadContext;
};
/**
* A function that handles data mutations for a route on the client
* @private Public API is exported from @remix-run/react
*/
type ClientActionFunction = (args: ClientActionFunctionArgs) => ReturnType<RRActionFunction>;
/**
* Arguments passed to a route `clientAction` function
* @private Public API is exported from @remix-run/react
*/
export type ClientActionFunctionArgs = RRActionFunctionArgs<undefined> & {
serverAction: <T = AppData>() => Promise<SerializeFrom<T>>;
};
/**
* A function that loads data for a route on the server
*/
export type LoaderFunction = (args: LoaderFunctionArgs) => ReturnType<RRLoaderFunction>;
/**
* Arguments passed to a route `loader` function
*/
export type LoaderFunctionArgs = RRLoaderFunctionArgs<AppLoadContext> & {
context: AppLoadContext;
};
/**
* A function that loads data for a route on the client
* @private Public API is exported from @remix-run/react
*/
type ClientLoaderFunction = ((args: ClientLoaderFunctionArgs) => ReturnType<RRLoaderFunction>) & {
hydrate?: boolean;
};
/**
* Arguments passed to a route `clientLoader` function
* @private Public API is exported from @remix-run/react
*/
export type ClientLoaderFunctionArgs = RRLoaderFunctionArgs<undefined> & {
serverLoader: <T = AppData>() => Promise<SerializeFrom<T>>;
};
export type HeadersArgs = {
loaderHeaders: Headers;
parentHeaders: Headers;
actionHeaders: Headers;
errorHeaders: Headers | undefined;
};
/**
* A function that returns HTTP headers to be used for a route. These headers
* will be merged with (and take precedence over) headers from parent routes.
*/
export interface HeadersFunction {
(args: HeadersArgs): Headers | HeadersInit;
}
/**
* A function that defines `<link>` tags to be inserted into the `<head>` of
* the document on route transitions.
*/
export interface LinksFunction {
(): LinkDescriptor[];
}
/**
* A function that returns an array of data objects to use for rendering
* metadata HTML tags in a route. These tags are not rendered on descendant
* routes in the route hierarchy. In other words, they will only be rendered on
* the route in which they are exported.
*
* @param Loader - The type of the current route's loader function
* @param MatchLoaders - Mapping from a parent route's filepath to its loader
* function type
*
* Note that parent route filepaths are relative to the `app/` directory.
*
* For example, if this meta function is for `/sales/customers/$customerId`:
*
* ```ts
* // app/root.tsx
* const loader = () => {
* return json({ hello: "world" } as const)
* }
* export type Loader = typeof loader
*
* // app/routes/sales.tsx
* const loader = () => {
* return json({ salesCount: 1074 })
* }
* export type Loader = typeof loader
*
* // app/routes/sales/customers.tsx
* const loader = () => {
* return json({ customerCount: 74 })
* }
* export type Loader = typeof loader
*
* // app/routes/sales/customers/$customersId.tsx
* import type { Loader as RootLoader } from "../../../root"
* import type { Loader as SalesLoader } from "../../sales"
* import type { Loader as CustomersLoader } from "../../sales/customers"
*
* const loader = () => {
* return json({ name: "Customer name" })
* }
*
* const meta: MetaFunction<typeof loader, {
* "root": RootLoader,
* "routes/sales": SalesLoader,
* "routes/sales/customers": CustomersLoader,
* }> = ({ data, matches }) => {
* const { name } = data
* // ^? string
* const { customerCount } = matches.find((match) => match.id === "routes/sales/customers").data
* // ^? number
* const { salesCount } = matches.find((match) => match.id === "routes/sales").data
* // ^? number
* const { hello } = matches.find((match) => match.id === "root").data
* // ^? "world"
* }
* ```
*/
export interface ServerRuntimeMetaFunction<Loader extends LoaderFunction | unknown = unknown, ParentsLoaders extends Record<string, LoaderFunction | unknown> = Record<string, unknown>> {
(args: ServerRuntimeMetaArgs<Loader, ParentsLoaders>): ServerRuntimeMetaDescriptor[];
}
interface ServerRuntimeMetaMatch<RouteId extends string = string, Loader extends LoaderFunction | unknown = unknown> {
id: RouteId;
pathname: AgnosticRouteMatch["pathname"];
data: Loader extends LoaderFunction ? SerializeFrom<Loader> : unknown;
handle?: RouteHandle;
params: AgnosticRouteMatch["params"];
meta: ServerRuntimeMetaDescriptor[];
error?: unknown;
}
type ServerRuntimeMetaMatches<MatchLoaders extends Record<string, LoaderFunction | unknown> = Record<string, unknown>> = Array<{
[K in keyof MatchLoaders]: ServerRuntimeMetaMatch<Exclude<K, number | symbol>, MatchLoaders[K]>;
}[keyof MatchLoaders]>;
export interface ServerRuntimeMetaArgs<Loader extends LoaderFunction | unknown = unknown, MatchLoaders extends Record<string, LoaderFunction | unknown> = Record<string, unknown>> {
data: (Loader extends LoaderFunction ? SerializeFrom<Loader> : AppData) | undefined;
params: Params;
location: Location;
matches: ServerRuntimeMetaMatches<MatchLoaders>;
error?: unknown;
}
export type ServerRuntimeMetaDescriptor = {
charSet: "utf-8";
} | {
title: string;
} | {
name: string;
content: string;
} | {
property: string;
content: string;
} | {
httpEquiv: string;
content: string;
} | {
"script:ld+json": LdJsonObject;
} | {
tagName: "meta" | "link";
[name: string]: string;
} | {
[name: string]: unknown;
};
type LdJsonObject = {
[Key in string]: LdJsonValue;
} & {
[Key in string]?: LdJsonValue | undefined;
};
type LdJsonArray = LdJsonValue[] | readonly LdJsonValue[];
type LdJsonPrimitive = string | number | boolean | null;
type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray;
/**
* An arbitrary object that is associated with a route.
*/
export type RouteHandle = unknown;
export interface EntryRouteModule {
clientAction?: ClientActionFunction;
clientLoader?: ClientLoaderFunction;
ErrorBoundary?: any;
HydrateFallback?: any;
Layout?: any;
default: any;
handle?: RouteHandle;
links?: LinksFunction;
meta?: ServerRuntimeMetaFunction;
}
export interface ServerRouteModule extends EntryRouteModule {
action?: ActionFunction;
headers?: HeadersFunction | {
[name: string]: string;
};
loader?: LoaderFunction;
}
export {};