T
tRPC

Automatically setting input for requests via OpenAPI

Automatically setting input for requests via OpenAPI

TTroy10/1/2023
My API allows users to authenticate via OpenAPI with an API key. The context either has ctx.user (when using the normal tRPC endpoints) or ctx.brand (when using API key) set. I have some middleware as follows, which checks the authorization and I am trying to automatically set the brandId input so that this does not need to be supplied for API key users (since the correct brand can be inferred from the key).
const isAuthed = t.middleware(({ ctx, next, rawInput }) => {
if (!ctx.user && !ctx.brand) {
throw new TRPCError({
message: 'Please authenticate.',
code: 'UNAUTHORIZED',
});
}

if (ctx.brand) {
// This will only be true when using API key, and we can infer the brand as it is associated to the particular API key (this is done in createContext).
(rawInput as { brandId: string }).brandId = ctx.brand.id;
}

return next({ ctx });
});
const isAuthed = t.middleware(({ ctx, next, rawInput }) => {
if (!ctx.user && !ctx.brand) {
throw new TRPCError({
message: 'Please authenticate.',
code: 'UNAUTHORIZED',
});
}

if (ctx.brand) {
// This will only be true when using API key, and we can infer the brand as it is associated to the particular API key (this is done in createContext).
(rawInput as { brandId: string }).brandId = ctx.brand.id;
}

return next({ ctx });
});
I am using rawInput, as this is the only way I could get this to work. Is there a better method for this, or is the correct way to do this? For reference, this is the start of one of my tRPC routes:
getIntegrations: protectedProcedure
.meta({
openapi: {
summary: 'Get integrations',
description:
'Returns the integrations associated with the brand with the specified ID.',
tags: ['Brand'],
method: 'GET',
// Notice the brandId is not supplied for OpenAPI requests
path: '/brand/integration',
protect: true,
},
})
.input(z.object({ brandId: z.string() }))
.output(
z.object({
integrations: z.array(IntegrationSchema.pick({ id: true, name: true })),
})
)
.query(...),
getIntegrations: protectedProcedure
.meta({
openapi: {
summary: 'Get integrations',
description:
'Returns the integrations associated with the brand with the specified ID.',
tags: ['Brand'],
method: 'GET',
// Notice the brandId is not supplied for OpenAPI requests
path: '/brand/integration',
protect: true,
},
})
.input(z.object({ brandId: z.string() }))
.output(
z.object({
integrations: z.array(IntegrationSchema.pick({ id: true, name: true })),
})
)
.query(...),
I am using trpc-openapi for the OpenAPI routing, though everything is set via the context anyway. If there is a way to conditionally set the input based on whether an API key is being used, that would be even better to keep my OpenAPI spec correct.
Hhaardik10/2/2023
look into zod's discriminated unions

Looking for more? Join the community!

T
tRPC

Automatically setting input for requests via OpenAPI

Join Server