yatta/next
Route handlers and request-scoped fetching for Next.js.
12 exported symbols and 0 members, read from src/react/next.ts.
Construct
forwardedHeaders
functionThe request headers a server render should forward.
A Server Component fetching on the server has to pass the caller's cookie on, or the API sees an anonymous request and returns 401 — which looks like a permissions bug rather than a missing header.
forwardedHeaders(request: Request): Record<string, string>getRequestCache
functionThe per-request cache.
Deliberately module-level and set by a provider per request. A module-level *value* that survives between requests would leak one user's data into the next response, so it must be replaced on every request and never outlive one.
getRequestCache(): Map<string, unknown> | undefinedreadBody
async functionReads a request body as text, for a platform that streams it.
Next.js has already consumed the stream by the time a route handler runs in some configurations, so `request.text()` can throw. Returns `undefined` rather than throwing, because an unreadable body on a route that takes no body is not an error worth failing the request over.
readBody(request: Request): Promise<string | undefined>releaseRequestCache
functionClears the request cache, taking the cache it was given.
releaseRequestCache(cache?: Map<string, unknown> | undefined): voidserverQuery
async functionServer-side data fetching for React Server Components.
Reads from the request cache instead of issuing a second request, which is the whole point: a Server Component and a client component below it should see one fetch, not two. Needs a `YattaProvider` above it in the server tree. If there is none, this fetches directly rather than throwing, so a component that is server-rendered on its own still works — it just does not share.
serverQuery<T>(key: readonly unknown[], fetcher: () => Promise<T>, options?: { revalidate?: number; }): Promise<T>// app/users/[id]/page.tsxexport default async function Page({ params }) { const user = await serverQuery(["getUser", params.id], () => api.getUser({ params: { id: params.id } }), ); return <Profile user={user} />;}toNextRequestLike
functionBuilds a `NextRequest`-shaped argument from the standard `Request`.
Next.js passes a `NextRequest`, which is a superset of `Request`. This exists so a handler can read the same headers either way without checking the type.
toNextRequestLike(request: Request): Request & { nextUrl?: URL; }toNextRoute
functionBuilds every HTTP method from one route table.
Next.js route handlers are exported per verb, so a table has to become seven named exports. Written out by hand that is seven chances to pass a different route table to one of them.
toNextRoute(app: App<any>, options?: AdapterOptions): Record<string, (request: Request) => Promise<Response>>// app/api/[[...path]]/route.tsimport { toNextRoute } from "yatta/next";import { routes } from "@/api-contract";import { handlers } from "@/api-handlers"; export const { GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS } = toNextRoute(routes, { handlers });withRequestCache
functionScopes a cache to one request.
Call this at the top of a server tree, in a layout or middleware. Pass `undefined` afterwards — leaving a cache in place after the request has been served is how two users see each other's data.
withRequestCache(): Map<string, unknown>// app/layout.tsxexport default function RootLayout({ children }) { const cache = withRequestCache(); try { return <>{children}</>; } finally { releaseRequestCache(cache); }}Types
AdapterOptions
typeAliases: these names read better from an adapter's point of view.
type AdapterOptions = TransportOptionsUniversalRequest
typetype UniversalRequest = WireRequestUniversalResponse
typetype UniversalResponse = WireResponseOther
mount
unknownmountAuthConfig or JobPayload — declaring your schema once is enough for the rest to follow. See Typed keys.