T
TanStack6mo ago
ugly-tan

Server function middleware that takes an argument

I'd like to use a server function middleware that ensures a user has a given permission before continuing. The middleware accepts a permission as an argument:
export const requirePermission = createMiddleware()
.middleware([requireUser])
.validator((data: Permission) => data)
.server(async ({ next, context, data }) => {
// Ensure user has permission
})
export const requirePermission = createMiddleware()
.middleware([requireUser])
.validator((data: Permission) => data)
.server(async ({ next, context, data }) => {
// Ensure user has permission
})
But I'm then getting stuck trying to figure out how to use this middleware with a server function that also takes its own arguments. So for a server function like this:
const getProjectById = createServerFn({ method: 'GET' })
.validator(
z.object({
projectId: z.string(),
}),
)
.handler(async ({ data, context }) => {
// Get the project from the database
})
const getProjectById = createServerFn({ method: 'GET' })
.validator(
z.object({
projectId: z.string(),
}),
)
.handler(async ({ data, context }) => {
// Get the project from the database
})
I can't call the middleware in the middleware array (get a type error):
const getProjectById = createServerFn({ method: 'GET' })
.middleware([() => requirePermission('project:read')])
.validator(
z.object({
projectId: z.string(),
}),
)
.handler(async ({ data, context }) => {
// Get the project from the database
})
const getProjectById = createServerFn({ method: 'GET' })
.middleware([() => requirePermission('project:read')])
.validator(
z.object({
projectId: z.string(),
}),
)
.handler(async ({ data, context }) => {
// Get the project from the database
})
I tried two separate validator() calls, one before the middleware and one after, but that didn't work either. Any guidance on how to achieve this would be greatly appreciated! Hopefully I'm missing something simple.
7 Replies
like-gold
like-gold6mo ago
you would need to be able to define a factory for that middlware I suspect we dont support this yet in our compiler so for now you would need to define separate middlewares per permission which obviously is not nice
ugly-tan
ugly-tanOP6mo ago
ah ok -- i think a factory would be an elegant enough solution. something like this:
export const requirePermission = (permission: Permission) =>
createMiddleware()
.middleware([requireUser])
.server(async ({ next, context }) => {
// Check permission
})
export const requirePermission = (permission: Permission) =>
createMiddleware()
.middleware([requireUser])
.server(async ({ next, context }) => {
// Check permission
})
seems pretty flexible and easy to use
like-gold
like-gold6mo ago
while it looks simple, we do static extraction in our compiler which I guess would break with this
ugly-tan
ugly-tanOP6mo ago
oh, got it
like-gold
like-gold6mo ago
but still, it might be possible in the future can you please create a github discussion feature request for this
ugly-tan
ugly-tanOP6mo ago
yep
ugly-tan
ugly-tanOP6mo ago
GitHub
Parameterized server function middleware · TanStack router · Disc...
I'm trying to implement a permission-based middleware system where server functions can be protected based on specific permission requirements: const requirePermission = createMiddleware() .mid...

Did you find this page helpful?