graphQL Query: getting error "Expected value of type ..., found ..." - graphql

Suppose I have the following object types:
type Price {
currency: Currency!,
amount: Float!
}
type Attribute {
displayValue: String,
value: String,
id: String!
}
type AttributeSet {
id: String!,
name: String,
type: String,
items: [Attribute]
}
type Product {
id: String!,
name: String!,
inStock: Boolean,
gallery: [String],
description: String!,
category: String!,
attributes: [AttributeSet]
prices: [Price!]!,
brand: String!
}
type Category {
name: String,
products: [Product]!
}
type Currency {
label: String!,
symbol: String!
}
input CategoryInput {
title: String!
}
type Query {
categories: [Category],
category(input: CategoryInput): Category,
product(id: String!): Product,
currencies: [Currency]
}
And these are the Types for Category:
export enum Category {
all = 'all',
clothes = 'clothes',
tech = 'tech'
};
In graphQL Playground, I am trying to make a query to exhibit all the names and products/id of the elements with the category all. Here's my attempt:
{
category(input: "all") {
name
products {
id
}
}
}
But I'm getting the following error message:
"message": "Expected value of type \"CategoryInput\", found \"all\".",
I need help trying to understand what went wrong since all is a valid type. Thank you in advance.

Just found my mistake
CategoryInput is of type
input CategoryInput {
title: String!
}
So a proper query would be:
{
category(input: { title: "all" }) {
name
products {
id
}
}
}

Related

Apollo Client: valid object type not being recognized

Here's my schema file:
import { gql } from 'apollo-server';
const typeDefs = gql`
type Price {
currency: Currency!,
amount: Float!
}
type Attribute {
displayValue: String,
value: String,
id: String!
}
type AttributeSet {
id: String!,
name: String,
type: String,
items: [Attribute]
}
type Product {
id: String!,
name: String!,
inStock: Boolean,
gallery: [String],
description: String!,
category: String!,
attributes: [AttributeSet]
prices: [Price!]!,
brand: String!
}
type Category {
name: String,
products: [Product]!
}
type Currency {
label: String!,
symbol: String!
}
input CategoryInput {
title: String!
}
type Query {
categories: [Category],
category(input: CategoryInput): Category,
product(id: String!): Product,
currencies: [Currency]
}
`;
export default typeDefs;
and these are the types of Category:
export enum Category {
all = 'all',
clothes = 'clothes',
tech = 'tech'
};
When in the graphQl playground, I tried to make a query like this:
{
category(input: "all") {
name
products {
id
name
}
}
}
I know that some required types are not being used - like gallery, description, etc... - but the error message I'm getting is:
Expected value of type "CategoryInput", found "all".
I would appreciate any help concerning why is this error message being exhibited, since "all" is a valid type for Category. Thank you in advance.
the input type is an object so you need to pass properties inside that object like this example :
{
category(input: {title:"all"}) {
name
products {
id
name
}
}
}

Not getting count according to filter in GraphQL amplify queries

Getting Scanned count but not count of data according to filter
count: null
items: [{id: "bcd75096-7fd9-4e9d-8675-6877f0609ac2", name: "dxfrdhjkhklklkl", description: "dgdxrfg",…},…]
0: {id: "bcd75096-7fd9-4e9d-8675-6877f0609ac2", name: "dxfrdhjkhklklkl", description: "dgdxrfg",…}
1: {id: "52f6ff60-fc07-4631-a1fb-b039f376ff21", name: "ghnfgyhj", description: "gyhkjmuhjolk",…}
2: {id: "f73dfb37-2778-4b87-88c7-e6f9f5b5c931", name: "drftgserty", description: "trse54rte54ty",…}
3: {id: "6df9f5c2-ec06-4e70-b5e2-133cb0d8e958", name: "tygujghukuh", description: "tuyjyuikuolnh",…}
4: {id: "9360a766-ac89-420c-881b-2b3089bcca7f", name: "kl;", description: "vcbghnjmk,l", is_active: true,…}
5: {id: "c0dcbaff-37d4-4e4c-9375-584ff7110d77", name: "dfhgbdcb", description: "dfxvcx", is_active: true,…},...
scannedCount: 100
I have followed these tutorials to get count HOW TO COUNT THE NUMBER OF RESULTS WITH AWS AMPLIFY DYNAMODB AND GRAPHQL
Filter
var body = {
filter: {
is_active: {
eq: true
}
}
}
Query to get list of todos
export const listTodos = /* GraphQL */ `
query ListTodos(
$filter: ModelTodoFilterInput
$limit: Int
$nextToken: String
) {
listTodos(filter: $filter, limit: $limit, nextToken: $nextToken) {
count
items {
id
name
description
is_active
createdAt
updatedAt
}
scannedCount
}
}
`;
GraphQl shema
type Todo #model {
id: ID!
name: String!
description: String!
is_active: Boolean
}
type ModelTodoConnection {
items: [Todo]
scannedCount: Int
count: Int
total: Int
}
And IF I set limit to 5 and it will send back scannedCount 5 if when I have total data in database around 110. I want to count data where is_active: { eq: true }
Check out the package I wrote to solve this issue: https://github.com/multimeric/AmplifyCountDirective.
After following the installation instructions, to solve your issue I would change the schema to this:
type Todo #model #count {
id: ID!
name: String!
description: String!
is_active: Boolean
}
Then you can query the count using a GraphQL query such as:
{
countTodo(filter: {
is_active: {
eq: true
}
})
}

graphql, how to design input type when there are "add" and "update" mutation?

Here are my requirements:
"add" mutation, every field(or called scalar) of BookInput input type should have additional type modifiers "!" to validate the non-null value. Which means when I add a book, the argument must have title and author field, like {title: "angular", author: "novaline"}
"update" mutation, I want to update a part of fields of the book, don't want to update whole book(MongoDB document, And, I don't want front-end to pass graphql server a whole big book mutation argument for saving bandwidth). Which means the book argument can be {title: "angular"} or {title: "angular", author: "novaline"}.
Here are my type definitions:
const typeDefs = `
input BookInput {
title: String!
author: String!
}
type Book {
id: ID!
title: String!
author: String!
}
type Query {
books: [Book!]!
}
type Mutation{
add(book: BookInput!): Book
update(id: String!, book: BookInput!): Book
}
`;
For now, "add" mutation works fine. But "update" mutation cannot pass the non-null check if I pass {title: "angular"} argument
Here is a mutation which does not pass the non-null check, lack of "author" field for BookInput input type.
mutation {
update(id: "1", book: {title: "angular"}) {
id
title
author
}
}
So, graphql will give me an error:
{
"errors": [
{
"message": "Field BookInput.author of required type String! was not provided.",
"locations": [
{
"line": 2,
"column": 24
}
]
}
]
}
How do I design the BookInput input type? Don't want to define addBookInput and updateBookInput. It's duplicated.
A very common pattern is to have separate input types for each mutation. You may also want to create one mutation query per operation. Perhaps something like this:
const typeDefs = `
input AddBookInput {
title: String!
author: String!
}
input UpdateBookInput {
# NOTE: all fields are optional for the update input
title: String
author: String
}
type Book {
id: ID!
title: String!
author: String!
}
type Query {
books: [Book!]!
}
type Mutation{
addBook(input: AddBookInput!): Book
updateBook(id: String!, input: UpdateBookInput!): Book
}
`;
Some people also like to include the update ID as part of the update input:
const typeDefs = `
input AddBookInput {
title: String!
author: String!
}
input UpdateBookInput {
# NOTE: all fields, except the 'id' (the selector), are optional for the update input
id: String!
title: String
author: String
}
type Book {
id: ID!
title: String!
author: String!
}
type Query {
books: [Book!]!
}
type Mutation{
addBook(input: AddBookInput!): Book
updateBook(input: UpdateBookInput!): Book
}
`;
Finally, you may want to use a 'payload' type for the return type - for added flexibility (gives you more wiggle room to change the return type later without breaking your API):
const typeDefs = `
input AddBookInput {
title: String!
author: String!
}
input UpdateBookInput {
# NOTE: all fields, except the 'id' (the selector), are optional for the update input
id: String!
title: String
author: String
}
type Book {
id: ID!
title: String!
author: String!
}
type AddBookPayload {
book: Book!
}
type UpdateBookPayload {
book: Book!
}
type Query {
books: [Book!]!
}
type Mutation{
addBook(input: AddBookInput!): AddBookPayload!
updateBook(input: UpdateBookInput!): UpdateBookPayload!
}
`;
Hope this helps!
Here is my solution, I write a helper function to generate "create" input type and "update" input type.
const { parse } = require('graphql');
/**
* schema definition helper function - dynamic generate graphql input type
*
* #author https://github.com/mrdulin
* #param {string} baseSchema
* #param {object} options
* #returns {string}
*/
function generateInputType(baseSchema, options) {
const inputTypeNames = Object.keys(options);
const schema = inputTypeNames
.map(inputTypeName => {
const { validator } = options[inputTypeName];
const validatorSchema = Object.keys(validator)
.map(field => `${field}: ${validator[field]}\n`)
.join(' ');
return `
input ${inputTypeName} {
${baseSchema}
${validatorSchema}
}
`;
})
.join(' ')
.replace(/^\s*$(?:\r\n?|\n)/gm, '');
parse(schema);
return schema;
}
schema.js:
${generateInputType(
`
campaignTemplateNme: String
`,
{
CreateCampaignTemplateInput: {
validator: {
channel: 'ChannelUnionInput!',
campaignTemplateSharedLocationIds: '[ID]!',
campaignTemplateEditableFields: '[String]!',
organizationId: 'ID!',
},
},
UpdateCampaignTemplateInput: {
validator: {
channel: 'ChannelUnionInput',
campaignTemplateSharedLocationIds: '[ID]',
campaignTemplateEditableFields: '[String]',
organizationId: 'ID',
},
},
},
)}

How to pass params to child property in GraphQL

i am pretty new to GraphQL, getting to become a huge fan :)
But, something is not clear to me. I am using Prisma with and GraphQL-Yoga with Prisma bindings.
I do not know how to pass params from my graphQL server to sub properties. Don't know if this is clear, but i will show it with code, thats hopefully easier :)
These are my types
type User {
id: ID! #unique
name: String!
posts: [Post!]!
}
type Post {
id: ID! #unique
title: String!
content: String!
published: Boolean! #default(value: "false")
author: User!
}
My schema.graphql
type Query {
hello: String
posts(searchString: String): [Post]
users(searchString: String, searchPostsTitle: String): [User]
me(id: ID): User
}
and my users resolver:
import { Context } from "../../utils";
export const user = {
hello: () => "world",
users: (parent, args, ctx: Context, info) => {
return ctx.db.query.users(
{
where: {
OR: [
{
name_contains: args.searchString
},
{
posts_some: { title_contains: args.searchPostsTitle }
}
]
}
},
info
);
},
me: (parent, args, ctx: Context, info) => {
console.log("parent", parent);
console.log("args", args);
console.log("info", info);
console.log("end_________________");
return ctx.db.query.user({ where: { id: args.id } }, info);
}
};
and my posts resolver
import { Context } from "../../utils";
export const post = {
posts: (parent, args, ctx: Context, info) => {
return ctx.db.query.posts(
{
where: {
OR: [
{
title_contains: args.searchString
},
{
content_contains: args.searchString
}
]
}
},
info
);
}
};
so, now :)
I am able to do the following when i am in the GraphQL playground on my prisma service:
{
user(where: {id: "cjhrx5kaplbu50b751a3at99d"}) {
id
name
posts(first: 1, after: "cjhweuosv5nsq0b75yc18wb2v") {
id
title
content
}
}
}
but i cant do it on the server, if i do something like that.. i am getting the error:
"error": "Response not successful: Received status code 400"
this is what i am trying:
{
me(id: "cjhrx5kaplbu50b751a3at99d") {
id
name
posts(first:1) {
id
title
content
}
}
}
does somebody know how i could do that?
since i have a custom type of user, posts does not have params like the generated one. Either i am using the the generated one, or modifying it to look like this:
type User {
id: ID!
name: String!
posts(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Post!]
}
EDIT 2018 June 4th
# import Post from './generated/prisma.graphql'
type Query {
hello: String
posts(searchString: String): [Post]
users(searchString: String, where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]
me(id: ID): User
}
type Mutation {
createUser(name: String!): User
createPost(
title: String!
content: String!
published: Boolean!
userId: ID!
): Post
}
I copied the params over from prisma.graphql manually.

Query.products is defined in resolvers but not in schema

Hi I defined rootQuery in Customer schema and then in Product schema I extended query. I wrote resolvers for product schema but then I got following error: Error: Query.products defined in resolvers, but not in schema.
When I move product queries to customer query definition it works.
I dont understand why I'm getting this error. Do I need implement some rootQuery and insert it into typeDefs array and then extend queries in Customer and Product ?
Customer schema
import CustomerPhoto from "./customerPhoto";
const Customer = `
type Customer {
customerID: ID!
firstname: String
lastname: String
phone: String
email: String
CustomerPhoto: CustomerPhoto
}
input CustomerInput {
firstname: String!
lastname: String!
phone: String!
email: String!
}
type Query {
customers(cursor: Int!):[Customer]
customer(id: Int!): Customer
}
type Mutation {
createCustomer(photo: String!, input: CustomerInput): Customer
updateCustomer(customerID: ID!, photo: String, input: CustomerInput): Customer
deleteCustomer(customerID: ID!): Customer
}
`;
export default [Customer, CustomerPhoto];
Product Schema
import ProductPhoto from "./productPhoto";
const Product = `
type Product {
productID: ID!
name: String!
description: String!
pricewithoutdph: Float!
pricewithdph: Float!
barcode: Int!
ProductPhoto: ProductPhoto
}
extend type Query {
products: [Product]
product(productID: ID!): Product
}
`;
export default [Product, ProductPhoto]
Here Im importing both schemas. Is there something missing ?
const schema = makeExecutableSchema({
typeDefs: [...Customer,...Product],
resolvers: merge(CustomerResolvers, ProductResolvers),
logger: {
log: e => {
console.log("schemaError", e);
}
},
resolverValidationOptions: {
requireResolversForNonScalar: true
}
});
Product Resolvers
const ProductResolvers = {
Query: {
products: (_, { cursor }) => {
return models.Product.findAndCountAll({
include: {
model: models.ProductPhoto,
attributes: ["productPhotoID", "photo"],
required: true
},
offset: cursor,
limit: 10,
attributes: ["productID", "name", "description", "pricewithoutdph", "pricewithdph", "barcode"]
}).then(response => {
return response.rows;
});
}
};
export default ProductResolvers;
Customer Resolvers
const CustomerResolvers = {
Query: {
customers: (_, {cursor}) => {
return models.Customer.findAndCountAll({
include: {
model: models.CustomerPhoto,
attributes: ["customerPhotoID", "photo"],
required: true
},
offset: cursor,
limit: 10,
attributes: ["customerID", "firstname", "lastname", "phone", "email"]
}).then(response => {
return response.rows;
});
}
......
}
};

Resources