Bundles a series of middleware into a single middleware.
build receives the composite's config and returns the parts, outermost first — the same order pipeline takes. The composite's contributions are derived from the parts', so it publishes exactly the union of what they contribute. There is no argument for declaring a key, so a composite cannot over-declare — and internal may only name a key some part actually contributes. Prerequisites are derived the same way — a part's In that an earlier part contributes is discharged internally, and anything outstanding becomes the composite's own In.
At runtime the parts fold exactly as pipeline folds them, each merging its own single key. A part that short-circuits therefore does so from inside the fold, where an enclosing middleware's response seam observes its response.
import { defineComposite } from '@supabase/middleware'
// `withGate` contributes the whole auth result at `ctx.auth`; the projections
// republish the individual keys the public contract promises. `auth` itself is
// an implementation detail, so it is marked internal.
export const withAuth = defineComposite({
build: (config: { mode: 'user' | 'none' }) =>
[withGate(config), withMode(), withClaims()] as const,
internal: ['auth'],
})
// Nested, or flat — one declaration serves both.
export default {
fetch: pipeline([withAuth({ mode: 'user' }), withPostgres()], async (req, ctx) => {
ctx.authMode // from withMode
ctx.jwtClaims // from withClaims
ctx.postgres // reads ctx.jwtClaims as its own `In`
return Response.json({ ok: true })
}),
}