There are packages that generate classes from prisma schema, like prisma-nestjs-graphql which i've been using recently.
This is an example:
// user.resolver.ts -----------------------------------
import { User, UserCreateInput } from 'src/@generated';
@Mutation(() => User, { nullable: true })
async createUser(
@Args('data') data: UserCreateInput
) {
return this.userService.createUser(data);
}
// user.service.ts ------------------------------------
async createUser(
data: UserCreateInput,
): Promise<User> {
return this.prisma.user.create({ data });
}
Setup
This is my basic setup, there're more configurations, see details
prisma.schema
generator nestgraphql {
provider = "node node_modules/prisma-nestjs-graphql"
output = "../src/@generated"
fields_Validator_from = "class-validator"
fields_Validator_input = true
requireSingleFieldsInWhereUniqueInput = true
emitSingle = true
emitCompiled = true
purgeOutput = true
noTypeId = true
}
that's it! And run npx prisma generate, which generates classes in the defined path /src/@generated/index.ts
Bonus!!!
I also parse requested graphql schema to prisma select so tha only requested fields will be queried from db and also if your query has nested relations, you will not have to define separate resolve fields, otherwise you'll need to define resolve fields for every nested relations
Example:
// user.resolver.ts -----------------------------------
import PrismaSelect from 'src/decorators/prisma-select';
import { User, UserCreateInput } from 'src/@generated';
@Mutation(() => User, { nullable: true })
async createUser(
@Args('data') data: UserCreateInput,
@PrismaSelect() select: Prisma.UserSelect, // <----- here is the change
) {
return this.userService.createUser(data, select);
}
// user.service.ts ------------------------------------
async createUser(
data: UserCreateInput,
select: Prisma.UserSelect // <----- here is the change
): Promise<User> {
return this.prisma.user.create({ data, select });
}
// src/decorators/prisma-select.ts
import { prismaSelect } from '@src/utils/prisma'
const PrismaSelect = createParamDecorator(
(_data: any, ctx: ExecutionContext) => {
const gqlCtx = GqlExecutionContext.create(ctx);
const info = gqlCtx.getInfo();
return prismaSelect(info);
},
);
export default PrismaSelect;
// @src/utils/prisma.ts
import { GraphQLResolveInfo } from 'graphql';
import graphqlFields from 'graphql-fields';
export const prismaSelect = (
info: GraphQLResolveInfo,
) => {
const parsedFields = graphqlFields(info);
const parse = (fields: any) => {
let result: any = {};
for (const key in fields) {
if (key === '__typename') {
delete fields[key];
continue;
}
const value = fields[key];
if (
typeof value !== 'object' ||
!Object.keys(value).length
) {
result[key] = true;
} else {
result[key] = {
select: parse(fields[key]),
};
}
}
return result;
};
return parse(parsedFields);
};
Lastly, put this prisma middleware which checks and removes nullable fields to prevent errors:
// src/middlewares/index.ts
import { Prisma } from '@prisma/client';
export function PrismaExcludeNullableFieldsMiddleware<
T extends Prisma.BatchPayload = Prisma.BatchPayload,
>(): Prisma.Middleware {
return async (
params: Prisma.MiddlewareParams,
next: (params: Prisma.MiddlewareParams) => Promise<T>,
): Promise<T> => {
const args = params.args || {};
for (const key in args) {
const nullable = !args[key] ?? !Object.keys(args[key]).length;
if (nullable) delete args[key];
}
if (args?.select && !Object.keys(args.select).length) {
args.select.id = true;
}
return next(params);
};
}
I have simplified these last codes, if that i broke something, don't mind!, you generally get the point, you can fix, if you can't and you're still interested in this bonus part, i can share the full setup.
Edit
// @src/utils/prisma.ts
import { PrismaSelect } from '@paljs/plugins';
export const prismaSelect = (
info: GraphQLResolveInfo
) => {
const prismaSelect = new PrismaSelect(info).value.select;
return prismaSelect
}
i found out this @paljs/plugins library that defines prisma select query fields from graphql info, before i was doing it myself and in some scenarios i had errors, this library is doing better that my custom approach
» npm install prisma-nestjs-graphql
nestjs - How can I use Prisma types on a nest.js GraphQL query argument - Stack Overflow
Anybody using NestJS along Prisma and GraphQL? How is your experience with it? do you recommend it ?
Integrate Prisma 2 into Nestjs applications
Loving the design of your blog!
More on reddit.com