Skip to content

Instantly share code, notes, and snippets.

@KATT
Created January 31, 2022 13:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KATT/7b2cf31593f68f9a288afb123c42c936 to your computer and use it in GitHub Desktop.
Save KATT/7b2cf31593f68f9a288afb123c42c936 to your computer and use it in GitHub Desktop.
Output data validation for tRPC
import { z } from 'zod';
import { TRPCError } from '@trpc/server';
/**
* Output parser. Example use-cases:
* - Resolvers where you touch sensitive data that you don't wanna risk leaking
* - Hairy resolvers where it's hard to follow what the resolver returns
* @param schema Zod Schema
* @param output The output
* @returns A parsed output, guaranteed to conform to the schema
*/
export function output<TSchema extends z.ZodTypeAny>(
schema: TSchema,
output: TSchema['_input'],
): TSchema['_output'] {
try {
return schema.parse(output);
} catch (cause) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'Output validation failed',
cause,
});
}
}
import { createRouter } from 'server/createRouter';
import { z } from 'zod';
import { TRPCError } from '@trpc/server';
import { output } from 'server/lib/output';
export const postRouter = createRouter()
.query('byId', {
input: z.object({
id: z.string(),
}),
async resolve({ ctx, input }) {
const { id } = input;
const post = await ctx.prisma.post.findUnique({
where: { id },
select: {
id: true,
title: true,
text: true,
createdAt: true,
updatedAt: true,
},
});
if (!post) {
throw new TRPCError({
code: 'NOT_FOUND',
message: `No post with id '${id}'`,
});
}
// Strictly validate the output before returning the result
return output(
z.object({
id: z.string(),
title: z.string(),
text: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
}),
post,
);
},
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment