Skip to content

ExamplesMiddleware

Middleware

Request middleware for logging, transformation, and error handling.

both modes

Middleware Configuration

Middleware functions are defined on the source. They run in order for every request.

ts
import { defineApi } from "@noverax/courier/define"
import { logMiddleware, authMiddleware } from "@noverax/courier/middleware"

const api = defineApi({
  baseURL: "http://localhost:4000",
  middleware: [
    logMiddleware(),
    authMiddleware(() => getAuthToken()),
    // Custom middleware
    async (ctx, next) => {
      console.log(`[${ctx.source}] ${ctx.method}`)
      const response = await next()
      return {
        ...response,
        data: {
          ...response.data as Record<string, unknown>,
          _meta: { timestamp: new Date().toISOString() },
        },
      }
    },
  ],
  groups: { users, misc },
})

Middleware receives a context object and a next function. Call next() to continue the chain and get the response. You can modify both the request context and the response.

Middleware docs

Response Transformation

Middleware can transform responses — for example, adding metadata to every response.

ts
// Middleware transforms responses — adds _meta to every response
const data = await caller.users.getAll()

// data now contains:
// {
//   data: [...users],
//   total: 3,
//   _meta: {
//     timestamp: "2025-01-01T00:00:00.000Z"
//   }
// }
middlewareQ.users.useQuery("getAll")SANDBOX
idle
// run the request to see the response

Error Handling

Wrap next() in try/catch to handle errors. Useful for logging and monitoring.

ts
// Error middleware catches errors before they reach the client
// Useful for server-side logging, monitoring, error tracking

async (ctx, next) => {
  try {
    return await next()
  } catch (error) {
    console.error(`[${ctx.source}] ${ctx.method}`, error)
    throw error // re-throw to let the caller handle it
  }
}
middlewareCaller.misc.error({ code: 500 })SANDBOX
idle
// run the request to see the response

Built-in Log Middleware

Use logMiddleware() for automatic request logging with timing.

ts
// Built-in logMiddleware logs every request
import { logMiddleware } from "@noverax/courier/middleware"

const api = defineApi({
  baseURL: "...",
  middleware: [logMiddleware()],
  groups: { ... },
})

// Logs: [courier] api users:getAll 200 45ms

Check your server terminal after running the demos above — logMiddleware logs every request with source, endpoint, status, and duration.