Utilities
Before You Reach For These
Most applications only need:
Server- route tables
- middleware
createContextKey()
The helpers on this page are mainly useful if you are:
- composing handlers programmatically
- integrating
festinto another host runtime - building higher-level abstractions on top of
fest - coordinating request-scoped async work manually
Import
import {
createServerRequest,
createWaitUntil,
raceRequestAbort,
runMiddleware,
toServerHandlerObject,
wrapFetch,
type HTTPMethod,
type MaybePromise,
} from "@hornjs/fest";
createServerRequest()
Turn an existing Request into a ServerRequest.
This is the low-level helper behind server.createRequest(). In normal
application code, prefer server.createRequest(request) when you already have
a Server instance.
createServerRequest() is most useful when you need to derive a new request
while preserving invocation state from an existing ServerRequest.
import { createServerRequest, type ServerRequest } from "@hornjs/fest";
function replaceHeaders(request: ServerRequest, headers: HeadersInit) {
return createServerRequest(new Request(request, { headers }), {
context: request.context,
runtime: request.runtime,
waitUntil: request.waitUntil,
originalRequest: request._request ?? request,
params: request.params,
});
}
The resulting ServerRequest keeps the expected fest fields such as:
contextruntimewaitUntil_requestparamsclone()
raceRequestAbort()
Tie async work to a request's abort signal.
If the request aborts before the promise settles, the returned promise rejects with the abort reason.
import { raceRequestAbort } from "@hornjs/fest";
async function readUser(request: Request) {
return raceRequestAbort(fetch("https://example.com/api/user"), request);
}
This is useful when you are writing helpers that should stop surfacing results for requests the client has already abandoned.
createWaitUntil()
Create a small registry for background tasks.
This mirrors service-worker-style waitUntil() behavior: register promises as
work that should still be awaited later.
import { createWaitUntil } from "@hornjs/fest";
const waiter = createWaitUntil();
waiter.waitUntil(sendAnalytics());
waiter.waitUntil(writeAuditLog());
await waiter.wait();
Rejected promises are logged and removed so a later wait() call can still
finish cleanly.
Handler Composition
toServerHandlerObject()
Normalize a bare handler or handler object into the object form used by
fest.
const handlerObject = toServerHandlerObject((request) => {
return new Response(`Hello ${new URL(request.url).pathname}`);
});
await handlerObject.handleRequest(request);
This is useful when your own abstraction wants to accept either:
- a bare
ServerHandler - or a
{ handleRequest, middleware }object
runMiddleware()
Execute a middleware chain against a terminal handler.
const response = await runMiddleware(
middleware,
request,
async (request) => new Response(new URL(request.url).pathname),
);
runMiddleware() is a low-level primitive. Callers are expected to pass a
valid ServerRequest, not a raw Request.
If the terminal handler is a handler object with its own middleware, that
inner middleware runs after the outer middleware array completes.
wrapFetch()
Compose a Server instance into the final fetch-style request kernel.
Server uses this internally after plugins and runtime adapter setup. You
usually do not need it unless you are testing or building a custom abstraction
around Server.
const kernel = wrapFetch(server);
const response = await kernel(server.createRequest(new Request("http://localhost/")));
Type Helpers
MaybePromise<T>
Use MaybePromise<T> for APIs that may return either a sync value or a
promise.
type Loader<T> = () => MaybePromise<T>;
HTTPMethod
HTTPMethod is the string union used by route-table method maps:
GETPOSTPUTDELETEPATCHHEADOPTIONS