Problems to filter with GRAPHQL (strapi) - graphql

I have a footer type:
type Footer {
id: ID!
created_at: DateTime!
updated_at: DateTime!
name: String
title: String
channel: Channel
footerMenu: [ComponentFooterFooterItem]
footerSocialMenu: [ComponentFooterFooterSocialMenu]
copyright: String
published_at: DateTime
}
And this queries for them:
footer(id: ID!, publicationState: PublicationState): Footer
footers(sort: String, limit: Int, start: Int, where: JSON, publicationState: PublicationState): [Footer]
Im trying to filter query but it dosent works.
query {
footer(channel) {
title
name
channel {
name
code
description
}
footerMenu {
label
route
icon
}
footerSocialMenu {
label
url
icon
}
copyright
}
}
This is the error. I just can input id or publication state.
"errors": [
{
"message": "Unknown argument \"channel\" on field \"Query.footers\".",
"locations": [
{
"line": 2,
"column": 11
}
],
I need to filter both queries by channel.code === "web". How can i do that?

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
}
}
}

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

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
}
}
}

Laravel lighthouse morphOne mutation

I want to allow users to upload images with their post but also have the ability to allow the users to upload images for the landingspage via a morphOne relation.
I set up my models according to the laravel docs but can provide them if needed.
than in my schema.graphql file I have the following
// schema.graphql
type Query
type Mutation
union Imageable = Blog | Landingspage
#import graphql/blog/*.graphql
#import graphql/landingspage/*.graphql
#import graphql/image/image.graphql
inside of the image.graphql file I have the following
// image.graphql
extend type Mutation {
createImage(input: ImageInput! #spread): Image #create
updateImage(input: ImageInput! #spread): Image #update
deleteImage(input: ImageInput! #spread): Image #delete
}
type Image {
id: ID!
url: String!
imageable: Imageable! #morphTo
}
input ImageInput {
id: ID!
url: String
imageable:ImageableMorphTo
}
input ImageableMorphTo {
connect: ImageableInput
disconnect: Boolean
delete: Boolean
}
input ImageableInput {
type: String!
id: ID!
}
and lastly in my blog.graphql file I have this
// blog.graphql
extend type Query {
blogs: [Blog!]! #all #orderBy(column: "created_at", direction: DESC)
blog(slug: String! #eq): Blog #find
}
extend type Mutation {
createBlog(input: CreateBlogInput #spread): Blog #create
}
type Blog {
id: ID!
title: String!
big_text: String!
small_text: String!
slug: String!
category_id: Int
created_at: DateTime!
updated_at: DateTime!
image: Image #morphOne
}
input CreateBlogInput {
title: String!
big_text: String!
small_text: String!
category_id: Int,
image: ImageInput
}
Now when I go to the graphql-playground and create the mutation
mutation ($input: CreateBlogInput ){
createBlog(input:$input){
id
title
small_text
big_text
image{
id
url
}
}
}
with the following input
{
"input": {
"title": "image-test",
"big_text": "big_text",
"small_text": "small_text",
"category_id": 2,
"image": {
"id": 3,
"url": "https://cats.example/cute"
}
}
}
my response is this
{
"data": {
"createBlog": {
"id": "7",
"title": "image-test",
"small_text": "small_text",
"big_text": "big_text",
"image": null
}
}
}
How do I make image not null anymore? I tried to reverse engineer the example at
https://lighthouse-php.com/master/eloquent/nested-mutations.html#morphto
but this only shows you how to create a image and connect a post (or blog) to it, but I want to create a post with an image.
Firstly, if you want that your image field were not null, just add a !, so:
type Blog {
# ...
image: Image! #morphOne
}
Secondly, if you want to create a Blog with an Image, the input should be like:
extend type Mutation {
createBlog(input: CreateBlogInput #spread): Blog #create
}
input CreateBlogInput {
title: String!
big_text: String!
small_text: String!
category_id: Int,
image: BlogImageRelationInput
}
input BlogImageRelationInput {
upsert: UpsertImageInput
}
input UpsertImageInput {
id: ID
url: String
}

How to write graphql query wiith custom objects

The server side of graphql is with nodejs and express. This is the schema for graphql. It has one query which accepts DateT object having from and to dates.
var schema = buildSchema(`
type Query {
courseWithDate(
timeFilter: DateT
): Course
},
type Course {
...
from: String
to: String
},
type DateT{
from : String
to : String
}
`);
and this is how I am getting courses
I am able to run the application with this url
localhost:4000/graphql
This is the query I am using
query courseWithDate($from: dateFrom, $to: dateTo) {
courseWithDate(timeFilter: {
from: "${dateFrom}"
to: "${dateTo}"
}) {
title
...
}
}
with these parameters
{
"from": "2019-10-10","to":"2019-10-10"
}
Exception message I get is related to the input type I am trying to pass.
{
"errors": [
{
"message": "The type of Query.courseWithDate(timeFilter:) must be Input Type but got: DateT.",
"locations": [
{
"line": 6,
"column": 25
}
]
}
]
}
I'm not sure, but probably this style looks more like best practice
type Course {
id: Int
title: String
author: String
from: String
to: String
description: String
topic: String
url: String
}
input DateInput {
dateFrom: String!
dateTo: String!
}
type Query {
courseWithDate(input: DateInput!, name: String!): Course
}
And Query on client side should be:
{
courseWithDate(input: {
dateFrom: "${dateFrom}"
dateTo: "${dateTo}"
}
name: "${name}")
{
id
name
}
}

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',
},
},
},
)}

Resources