Middleware

Use Typeweaver server middleware to add cross-cutting behavior around generated routes: auth, CORS, logging, security headers, request IDs, and custom typed middleware.

This middleware system belongs to @rexeus/typeweaver-server. If you choose the Hono plugin instead, you can still use Typeweaver for typed handlers, but you will usually lean on Hono's own middleware ecosystem.

Why middleware exists here

The generated server plugin already handles routing plus request and response validation. Middleware is for behavior that sits around that core flow, such as:

  • authentication
  • response headers
  • logging
  • request-scoped state
  • path-based guards

Built-in middleware

@rexeus/typeweaver-server includes ready-to-use middleware for common needs:

  • cors
  • basicAuth
  • bearerAuth
  • logger
  • secureHeaders
  • requestId
  • poweredBy
  • scoped
  • except
import {
  bearerAuth,
  cors,
  logger,
  requestId,
  secureHeaders,
} from "@rexeus/typeweaver-server";

const app = new TypeweaverApp()
  .use(cors())
  .use(secureHeaders())
  .use(logger())
  .use(requestId())
  .use(
    bearerAuth({
      verifyToken: async token => token === "demo-token",
    })
  )
  .route("/api", todoRouter);

For most apps, start with built-ins before writing custom middleware.

Custom middleware with defineMiddleware(...)

You can define typed custom middleware with defineMiddleware(...). In generated projects, it can be imported from the generated server helpers path.

import { defineMiddleware } from "./api/generated/lib/server";

const timing = defineMiddleware(async (ctx, next) => {
  const startedAt = Date.now();
  const response = await next();

  return {
    ...response,
    header: {
      ...response.header,
      "x-response-time-ms": String(Date.now() - startedAt),
    },
  };
});

This is a good fit for transport concerns that should apply to many routes.

Path-based middleware

Use scoped(...) and except(...) when a middleware should only run on some paths.

import { cors, except, logger, scoped } from "@rexeus/typeweaver-server";

const app = new TypeweaverApp()
  .use(scoped(["/api/*"], cors()))
  .use(except(["/health"], logger()));

This keeps route-specific behavior out of your handlers.

When to use middleware vs the spec

Use the spec for request and response contracts.

Use middleware for behavior around those contracts.

Good middleware concerns include auth, tracing, and response headers. Request field rules still belong in Zod request schemas.

Was this page helpful?