Controller

Grouping for routes that share a path prefix and a common preamble.

A Controller is a thin factory: each method constructs the corresponding RouteBase subclass with the prefix already joined on, records its id, and returns it. The routes are ordinary routes registered on the nearest App exactly as if they had been constructed directly — a controller adds no dispatch layer of its own.

import { Controller } from "@ozanarslan/corpus";

const users = new Controller("/users");
users.beforeEach = (c) => authenticate(c);

users.route("GET /:id", (c) => findUser(c.params.id));
Contents
  1. Controller

Controller

class

class Controller<Px extends Optional<string>= Optional<string>>

Registers routes under a shared path prefix.

Every method mirrors the constructor of the route class it creates, so moving a route into a controller means changing the call site and nothing else. The prefix is folded into the endpoint at construction time and into the endpoint type through WithPrefix, so the returned route stays as narrowly typed as one written out by hand.

Controller.beforeEach runs ahead of the handler for the route kinds that have a user-supplied handler — Controller.route and Controller.staticRoute. The other kinds resolve their responses internally and are unaffected.

Controller.routeIds makes the group addressable afterwards, which is how a Middleware can be attached to every route in a controller at once.

Type parameters

Controller.constructor()

constructor(public prefix?: Px)

Creates a controller.

Parameters

Controller.routeIds

readonly routeIds: Set<string>

Ids of every RouteBase registered through this controller, in the order they were created.

Pass them to a Middleware to target the whole group:

new Middleware([...users.routeIds], handler);

Controller.beforeEach

beforeEach?: ContextHandler

Runs before the handler of every Controller.route and Controller.staticRoute created by this controller.

Its return value is discarded — this is for side effects on the Context, such as authenticating a request or populating Context.data. Throwing here aborts the request before the handler runs, which is the intended way to reject one.

Assign it before registering routes: each route captures the controller, not the function, but a route registered while it is unset still checks it at request time. For behaviour that must wrap the response as well as precede it, use a Middleware targeting Controller.routeIds instead.

Controller.route()

route<B = unknown, S = unknown, P = unknown, R = unknown, E extends string = string>(...args: ConstructorParameters<typeof Route<B, S, P, R, E>>): Route<B, S, P, R, WithPrefix<Px, E>>

Registers a dynamic route under this controller. Behaves identically to Route but automatically prepends the controller prefix and runs beforeEach before the handler.

Type parameters

Parameters

Returns — The registered Route, its endpoint type prefixed.

Controller.staticRoute()

staticRoute<B = unknown, S = unknown, P = unknown, E extends string = string>(...args: ConstructorParameters<typeof StaticRoute<B, S, P, E>>): StaticRoute<B, S, P, WithPrefix<Px, E>>

Registers a static route under this controller. Behaves identically to StaticRoute but automatically prepends the controller prefix.

Controller.beforeEach runs only when a callback is supplied, since that is where the controller has a handler to wrap; a static route that just serves its file is left alone.

Type parameters

Parameters

Returns — The registered StaticRoute, its endpoint type prefixed.

Controller.fileRoute()

fileRoute<E extends string = string>(...args: ConstructorParameters<typeof FileRoute<E>>): FileRoute<WithPrefix<Px, E>>

Registers a file route under this controller. Behaves identically to FileRoute but automatically prepends the controller prefix.

Controller.beforeEach does not apply: a file route resolves its response internally and takes no handler to wrap.

Type parameters

Parameters

Returns — The registered FileRoute, its endpoint type prefixed.

Controller.websocketRoute()

websocketRoute<E extends string = string>(...args: ConstructorParameters<typeof WebSocketRoute<E>>): WebSocketRoute<WithPrefix<Px, E>>

Registers a websocket route under this controller. Behaves identically to WebSocketRoute but automatically prepends the controller prefix.

The address is a plain endpoint rather than a method-and-endpoint pair, since an upgrade is always a Method.GET. Controller.beforeEach does not apply — the socket lifecycle callbacks are not a ContextHandler.

Type parameters

Parameters

Returns — The registered WebSocketRoute, its endpoint type prefixed.

Controller.bundleRoute()

bundleRoute<E extends string = string>(...args: ConstructorParameters<typeof BundleRoute<E>>): BundleRoute<WithPrefix<Px, E>>

Registers a bundle route under this controller. Behaves identically to BundleRoute but automatically prepends the controller prefix.

Controller.beforeEach does not apply: a bundle route resolves files internally and takes no handler to wrap.

Type parameters

Parameters

Returns — The registered BundleRoute, its endpoint type prefixed.