- You have to use Prisma as your ORM
- Use NestJS or any other framework for backend
- https://nestjs.com/ - NestJS
- https://docs.nestjs.com/recipes/prisma#prisma - NestJS Prisma recipe
- You have to use Apollo Server
- https://www.apollographql.com/docs/apollo-server/ - Apollo Server
- https://docs.nestjs.com/graphql/quick-start - NestJS Apollo Server recipe
This package allow you to parse your GraphQL request and convert it to Prisma include and select objects
You can have one request and get any nested data you want
npm i @nazariistrohush/gql-prisma-select
info
-GraphQLResolveInfo
objectoptions
-object
with optionsoptions.get
-string | string[]
String split by.
or an array to get custom path of selection (similar to lodash.get)options.exclude
-string[]
Fields to exclude from selection__typename
excluded by default (because not exists in prisma model)
include
-object
with include object for Prismaselect
-object
with select object for PrismaoriginalInclude
-object
with original include object (same asinclude
in caseget
option is not used)originalSelect
-object
with original select object (same asselect
in caseget
option is not used)
GQLPrismaSelect.get(selection, path)
- get some specific selections by pathselection
-object
with selection ({ include, select } result ofnew GQLPrismaSelect(info, options)
constructor)path
-string | string[]
String split by.
or an array- Used to get specific selection from select/include object
E.g. get different selections from one GQLPrismaSelect constructor call
const includeSelect = new GQLPrismaSelect(info);
const { include, select } = GQLPrismaSelect.get(
includeSelect,
'collection.User'
);
const { include: includePosts, select: selectPosts } = GQLPrismaSelect.get(
includeSelect,
'collection.Post'
);
Get info from your request using @nestjs/graphql
Import GQLPrismaSelect
and GraphQLResolveInfo
import {
GQLPrismaSelect,
GraphQLResolveInfo,
} from '@nazariistrohush/gql-prisma-select';
@Query(() => Result)
someResolver(@Info() info: GraphQLResolveInfo) {
// "info" is what you need
const { include, select } = new GQLPrismaSelect(info);
}
Get forth argument in your resolver https://www.apollographql.com/docs/apollo-server/data/resolvers/#handling-arguments
someResolver(parent, args, context, info) {
// "info" is what you need
const { include, select } = new GQLPrismaSelect(info);
}
Then use it in Prisma.findUnique/findMany/findOne/updateOne/deleteOne etc...
model User {
id Int @id @unique @default(autoincrement())
email String @unique
Posts Post[]
}
model Post {
id Int @id @unique @default(autoincrement())
content String
User User @relation(fields: [userId], references: [id])
userId Int
}
Make sure fields in Graphql are same named as in your prisma model
Describe User Post types according to your prisma model (have in separate files)
@ObjectType()
export class User {
@Field(() => Int)
id: number;
@Field(() => String)
email: string;
@Field(() => [Post], { nullable: true, defaultValue: [] })
Posts?: Post[];
}
@ObjectType()
export class Post {
@Field(() => Int)
id: number;
@Field(() => String)
content: string;
@Field(() => Int)
userId: number;
@Field(() => User)
User: User;
}
Or in case you are using schema first approach
type User {
id: Int!
email: String!
Posts: [Post!] = []
}
type Post {
id: Int!
content: String!
userId: Int!
User: User!
}
Describe User service findOne method
@Injectable()
export class UsersService {
constructor(private prisma: PrismaService) {}
// findUniqueUserArgs already contains "select" and "include" which you can use to:
// get your any nested data using include
// filter fields of result by using select
findOne(findUniqueUserArgs: Prisma.UserFindUniqueArgs) {
return this.prisma.user.findUnique({
...findUniqueUserArgs,
});
}
}
Or use prisma.user.findUnique()
directly in your resolver (not recommended)
import { Args, Info, Int, Query, Resolver } from '@nestjs/graphql';
import {
GQLPrismaSelect,
GraphQLResolveInfo,
} from '@nazariistrohush/gql-prisma-select';
@Resolver(() => User)
export class UserResolver {
// Inject your service
constructor(private readonly userService: UserService) {}
@Query(() => User)
async user(
// Use this from @nestjs/graphql to get info of your request
@Info() info: GraphQLResolveInfo,
@Args('id', { type: () => Int }) id: number
) {
// This will parse your request and return include and select objects
const { include, select } = new GQLPrismaSelect(info);
// Pass include and select to your service to get any requested data
return this.userService.findOne({ where: { id }, include, select });
}
}
Or in case you are using schema first approach
import {
GQLPrismaSelect,
GraphQLResolveInfo,
} from '@nazariistrohush/gql-prisma-select';
export default {
Query: {
user: async (parent, args, context, info: GraphQLResolveInfo) => {
const { include, select } = new GQLPrismaSelect(info);
// return userService.findOne({ where: { id }, include, select });
return prisma.user.findUnique({
where: { id: args.id },
include,
select,
});
},
},
};
To get only id and email of user
query {
user(id: 1) {
id
email
}
}
To get user with all posts
query {
user(id: 1) {
id
email
Posts {
id
content
}
}
}
You can also describe posts query and get each user per post, or without it :)