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
sevointo another host runtime - building higher-level abstractions on top of
sevo - coordinating request-scoped async work manually
Import
import {
createContextKey,
createWaitUntil,
InvocationContext,
raceRequestAbort,
runMiddleware,
toServerHandlerObject,
wrapFetch,
type HTTPMethod,
type MaybePromise,
} from "sevo";
InvocationContext
InvocationContext is the core object passed to handlers and middleware. It
contains the request, runtime capabilities, route parameters, and a context
map for sharing state.
Creating a context
Normally you don't create contexts manually - they are created by Server:
const ctx = server.createContext(request);
Deriving a context
Use with() to create a derived context with modifications:
const newCtx = ctx.with({
params: { id: "123" },
request: new Request(ctx.request, { headers: newHeaders }),
});
The new context inherits all values from the parent context's internal map.
Override request, params, capabilities, or waitUntil only when you
need a modified view for downstream code.
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 "sevo";
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 "sevo";
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
sevo.
const ctx = new InvocationContext({
request: new Request("http://localhost/hello"),
capabilities: {} as any,
params: {},
});
const handlerObject = toServerHandlerObject((ctx) => {
return new Response(`Hello ${new URL(ctx.request.url).pathname}`);
});
await handlerObject.handleRequest(ctx);
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 ctx = new InvocationContext({
request: new Request("http://localhost/hello"),
capabilities: {} as any,
params: {},
});
const response = await runMiddleware(
middleware,
ctx,
async (ctx) => new Response(new URL(ctx.request.url).pathname),
);
runMiddleware() is a low-level primitive. Callers are expected to pass a
valid InvocationContext, 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 request handler.
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.createContext(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