Write resolvers for nested type definitions - graphql

Suppose I have following type definition for my GraphQL API:
const typeDef = `
type Book {
title: String
author: Author
likes: Int
}
type Author {
id: String
name: String
age: Int
books: [Book]
}
type Query{
books(authorid: String!): Book
}
`
Then, how many resolvers do I need for this? Should I handle this query request with only one resolver books and return all books and author info or should I make many resolvers such as Query -> books, Book -> author and Author -> books? I am not sure how the modular schema and resolver works together.

No matter how many type(Book, Author etc) or input you use you need to provide .
const schema = `
type Mutation {
mutatePost(postId:Int) :Int
}
type Query {
hello: String
posts: [String]
books(authorId: String!): Book
}
`
You need to use same name as you defined in Query must be same in resolver
const resolvers = {
Query: {
async hello() {
return 'Hello';
},
async posts() {
return ['Hello', 'World];
},
async books(_, { authorId }) {
//Return data which you is defined in type Book
//return Book
}
},
Mutation: {
async mutatePost(_, {
postId
}, context) {
//return Integer
}
},
}
Only thing every Query and Mutation need queryResolver and mutationResolver

Related

How can I make GraphQL support int8 type in Supabase?

I'm creating a simple CRUD app to learn GraphQL and am using a Supabase postgres instance. All queries and mutations work fine except for one thing, I can't get the id field from my schemas because they are of type int8 on Supabase, and GraphQL only supports Int.
I'm getting this error when I try to get a row's id using the gql Int type in my type defs: GraphQLError: Int cannot represent non-integer value: 1
I know the solution involves creating a custom scalar type as in this example, but I'm not sure how to implement this type. Also, I cannot change this on Supabase's side, so I must find a way to handle this in gql. How can I handle this type in GraphQL?
TypeDefs:
export const typeDefs = `#graphql
type User {
id: Int!
name: String!
email: String!
age: Int!
verified: Boolean!
}
type Todo {
id: Int!
title: String!
description: String!
}
type Query {
# users queries
getAllUsers: [User]
getUser(email: String!): User
# todo queries
getAllTodos: [Todo]
getTodo(id: String!): Todo
}
type Mutation {
createUser(name: String!, email: String!, age: Int!): User
createTodo(title: String!, description: String!): Todo
}
`;
Resolvers:
import { GraphQLScalarType } from 'graphql';
import { prisma } from '../lib/db.js';
const BigInt = new GraphQLScalarType({
// how do I implement this type?
});
export const resolvers = {
BigInt,
Query: {
getAllUsers() {
return prisma.user.findMany();
},
getUser(parent, args) {
return prisma.user.findUnique({
where: {
email: args.email,
},
});
},
getAllTodos() {
return prisma.todo.findMany();
},
getTodo(parent, args) {
return prisma.todo.findUnique({
where: {
id: args.id,
},
});
},
},
// parent, arge are other arguments that get passes to resolvers automatically
Mutation: {
createUser(parent, args) {
return prisma.user.create({
data: args,
});
},
createTodo(parent, args) {
return prisma.todo.create({
data: args,
});
},
},
};
Solved this by using the graphql-type-ints package. You can just install it and then add the type you need to your schemas and resolvers. However, I don't quite understand why we need to do this. If someone could explain why Supabase uses int8 and that doesn't conform to graphql's Int I would appreciate it.

How to solve "mutation returning data null"?

i'm using apollo-server and want to learn graphql schema, queries and mutations but iam not getting correct resources for understing how mutation works and how to define mutation in resolvers
i have tried something like adding "mutation" similar to "query" in the resolvers but no use.
#schema
const typeDefs = gql`
type Book {
title: String
author: String
}
type Mutation {
addBook(title: String, author: String): Book
}
type Query {
getBooks: [Book]
}
`;
#resolvers
const resolvers = {
Query: {
getBooks: () => books
}
};
#querying in graphql playground
mutation{
addBook( title: "a sad love story",author:"pavan kalyan"){
title
author
}
}
#result i got
{
"data": {
"addBook": null
}
}
i want to get the title and author in the result same as the arguments iam passing in the query
and no error messages
You need to define the mutation in your resolvers:
const resolvers = {
Query: {
getBooks: () => books,
},
Mutation: {
addBook: (_, {input}) => {
// ... code to add book somewhere
const addedBook = insert(input.title, input.author);
return addedBook; // i.e. {title: input.title, author: input.author};
}
}
}

Get other related records (with id different that queried)

As a newbie to GraphQL I would appreciate some help in the following:
I have query which retrieves its author and that author's books. I would like the author's books to be author's other books, meaning - except the one being queried. What does it involve?
apollo-angular query:
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books { # <-- give me all _except_ the one with $id
name
year
id
}
}
}
}
`;
and in the schema.js (node.js server) I have something like:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
const { id } = args;
return Book.findById(id);
},
},
books: {
type: GraphQLList(BookType),
resolve() {
return Book.find({});
},
},
// ... other queries ...
}
})
The solution I am looking for should, obviously, not break other queries for books.
You should be able to achieve the exclusion by adding an argument to the Author type def and then appropriately using that argument in the resolver for books (which should be nested resolver on your Author type). Will need to adapt syntax for apollo-angular.
type Author {
id:
firstName: String
lastName: String
books(exclude: ID): [Book]
}
const resolverMap = {
Query: {
book(arent, args, ctx, info) {
...
}
},
Author: {
books(obj, args, ctx, info) {
// Use args.exclude passed to filter results
},
},
};
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books(exclude: $id) {
name
year
id
}
}
}
}
`;

Nested query and mutation in type-Graphql

I found a feature in graphql to write nested query and mutation, I tried it but got null. I found the best practices of building graphqL schema on Meetup HolyJs and the speaker told that one of the best ways is building "Namespaced" mutations/queries nested, in this way you can write some middlewares inside the "Namespaced" mutations/queries and for get the Child mutation you should return an empty array because if you return an empty array, Graphql understand it and go one level deep.
Please check the example code.
Example in graphql-tools
const typeDefs = gql`
type Query { ...}
type Post { ... }
type Mutation {
likePost(id: Int!): LikePostPayload
}
type LikePostPayload {
recordId: Int
record: Post
# ✨✨✨ magic – add 'query' field with 'Query' root-type
query: Query!
}
`;
const resolvers = {
Mutation: {
likePost: async (_, { id }, context) => {
const post = await context.DB.Post.find(id);
post.like();
return {
record: post,
recordId: post.id,
query: {}, // ✨✨✨ magic - just return empty Object
};
},
}
};
This is my Code
types
import { ObjectType, Field } from "type-graphql";
import { MeTypes } from "../User/Me/Me.types";
#ObjectType()
export class MeNameSpaceTypes {
#Field()
hello: string;
#Field({ nullable: true })
meCheck: MeTypes;
}
import { Resolver, Query } from "type-graphql";
import { MeNameSpaceTypes } from "./MeNamespace.types";
#Resolver()
export class MeResolver {
#Query(() => MeNameSpaceTypes)
async Me() {
const response = {
hello: "world",
meCheck:{}
};
return response;
}
}
Result of code
query {
Me{
hello
meCheck{
meHello
}
}
}
--RESULT--
{
"data": {
"Me": {
"hello": "world",
"meCheck": {
"meHello": null
}
}
}
}
I got a null instead a meHello resolver. Where am I wrong?
Namespaced mutations are against GraphQL spec as they are not guarranted to run sequentially - more info in this discussion in GitHub issue related to your problem:
https://github.com/MichalLytek/type-graphql/issues/64

Running a graphql query from inside a resolver - for nested data

I am implementing an apollo server graphql schema. All my schema definition are modules in .graphql files. All my resolvers are modules in .js files.
I have the following type :
productSchema.graphql
type Product {
_id: Int
company: Company
productSellingPrice: [PriceHistoryLog]
productName: String
category: String
productDetails: [ProductDetail]
globalId: Int
isActive: Boolean
}
extend type Query {
ProductList: [Product]
}
productDetailSchema.graphql
type ProductDetail {
_id: Int
company: Company
root: Product
catalogItem: CatalogItem
product: Product
isPerishable: Boolean
quantity: Float
isActive: Boolean
}
extend type Query {
ProductDetailsList(productId: Int!): [ProductDetail]
}
What I want to do is, when querying for ProductList, to run a ProductDetailsList query and resolve the field in product from there.
As you can see ProductDetail also have nested fields so I can't just query the DB for that field in the Product resolver.
Any ideas? I am kind of lost.
Edit:
this is my resolver code:
Product: {
company: product => product.companyId,
category: async product => {
try {
let res = await SaleModel.findOne({ productName:
product.productName }) ;
return res.productCategory;
} catch (err) {
console.log(err);
return "Mo Category found";
}
}
},
Query: {
async ProductList(obj, args, { companyId }) {
return await ProductModel.find({
companyId,
isActive: true
}).populate("companyId");
}
},

Resources