Server Instance
Creating a Server
import { Server } from "sevok";
import { NodeRuntimeAdapter } from "sevok/node";
const server = new Server({
adapter: new NodeRuntimeAdapter(),
routes: {
"/": () => new Response("hello"),
},
fetch: () => new Response("Not Found", { status: 404 }),
});
await server.ready();
console.log(server.url);
adapter is optional. In the common Bun, Deno, and Node.js cases you can omit
it entirely unless you need to customize native adapter options or force a
specific runtime configuration.
When omitted, Server lazily resolves a built-in adapter for the current
process with dynamic imports such as import("sevok/bun"),
import("sevok/deno"), and import("sevok/node"):
- Bun ->
BunRuntimeAdapter - Deno ->
DenoRuntimeAdapter - Node.js ->
NodeRuntimeAdapter
import { Server } from "sevok";
const server = new Server({
routes: {
"/": () => new Response("hello"),
},
fetch: () => new Response("Not Found", { status: 404 }),
});
await server.ready();
If you prefer, use the convenience factory:
import { serve } from "sevok";
import { NodeRuntimeAdapter } from "sevok/node";
const server = serve({
adapter: new NodeRuntimeAdapter(),
routes: {
"/": () => new Response("hello"),
},
fetch: () => new Response("Not Found", { status: 404 }),
});
Method Maps
Route entries can also dispatch by HTTP method instead of pointing to a single handler:
const server = new Server({
routes: {
"/users": {
GET: () => new Response("list"),
POST: () => new Response("create"),
"*": (ctx) => new Response(`Unhandled method: ${ctx.request.method}`),
},
},
fetch: () => new Response("Not Found", { status: 404 }),
});
Method resolution order is:
- explicit request method
GETforHEADrequests whenHEADis not defined*as a fallback for any remaining method
That makes * a route-local method fallback rather than a replacement for
explicit handlers.
Important Properties
server.options
The normalized options used to build the server.
server.url
The public URL reported by the runtime adapter once listening has started.
server.waitUntil
Register background tasks outside the request pipeline.
server.waitUntil?.(
Promise.resolve().then(() => {
console.log("background startup task");
}),
);
Lifecycle Events
Server extends the typed event system from @hornjs/evt. You can subscribe
to lifecycle transitions with standard event listeners.
serve
Emitted after the runtime adapter reports that the server is listening.
close
Emitted after shutdown completes and all waitUntil() tasks have settled.
error
Emitted when asynchronous runtime adapter initialization fails.
update
Emitted after the server's routing configuration is updated via updateRouting().
import { Server, ServerErrorEvent, ServerServeEvent, ServerUpdateEvent } from "sevok";
server.addEventListener("serve", (event: ServerServeEvent) => {
console.log("ready at", server.url);
});
server.addEventListener("error", (event: ServerErrorEvent) => {
console.error(event.error);
});
server.addEventListener("update", (event: ServerUpdateEvent) => {
console.log("routing updated:", event.reason);
});
Important Methods
server.fetch(request)
Runs a request through middleware, invocation context initialization, route matching, and the fallback fetch handler when needed.
server.serve()
Starts listening if the server has not already been started.
server.ready()
Waits until the adapter reports that the server is ready.
server.close(closeActiveConnections?)
Stops the runtime adapter and waits for registered background work.
await server.close();
await server.close(true);
Passing true asks the runtime adapter to terminate active connections when it
supports that behavior.
server.close() also dispatches the close lifecycle event once teardown is
finished.
server.updateRouting(options)
Updates the server's routing configuration at runtime without restarting.
await server.updateRouting({
routes: {
"/api": () => new Response("new api"),
"/*": () => new Response("Not Found", { status: 404 }),
},
middleware: [loggingMiddleware],
});
This method replaces the current request handler pipeline with new routes, middleware, error handlers, and fetch handler. The operation is atomic and safe to call while the server is actively handling requests.
If multiple updateRouting() calls are made concurrently, only the most recent
one will take effect. The method dispatches an update event after successfully
updating the routing configuration.
Manual Startup
Set manual: true when you want to delay listening:
const server = new Server({
adapter: new NodeRuntimeAdapter(),
manual: true,
routes: {
"/": () => new Response("ok"),
},
fetch: () => new Response("Not Found", { status: 404 }),
});
await server.serve();
await server.ready();
If you prefer event-driven coordination instead of awaiting ready(), listen
for serve and close directly.