Graphiql structure queries/mutations by categories - graphql

I am wondering is there any way of structuring graphql queries/mutations in a GraphiQL ide. Right now I have long list of queries/mutation in docs tab (see image below). What I want is to seperate them by categories (like users, customers, interns etc). Is this possible? or should I use some other tools?
:

It may be helpful if you simulate namespace with nested type resolver like following.
type UserQuery {
users: [User]
user(id: String): User
}
type InternQuery {
intern: Intern
interns: [Intern]
internCustomers: [Customer]
}
type Query {
userQuery: UserQuery
internQuery: InternQuery
}
In your query's resolvers, userQuery and internQuery just need to return empty object, and put your other resolvers into UserQuery and InternQuery.

GraphQL itself has no concept of namespacing for tools like GraphiQL to take advantage of. You may be able to build your own conventions and tools based on them, but you'll have to do all the legwork.

Related

How to workaround non existent types in Graphql query in Gatsby

I'm building a website with a blog section, and on deployment to production the blog will be empty. I'm having problems allowing an empty blog on my Gatsby site.
When I run npm run develop it will only work if I have some blogs - I want it to work before the blogs have been added.
The main issues I'm encountering is trying to accomidate fields not existing like allStrapiBlog and strapiBlog because there are no blogs.
I get errors like this on blog components, and on my nav component (where i have a query that a conditional uses).
15:17 error Cannot query field "allStrapiBlog" on type "Query" graphql/template-strings
Cannot query field "strapiBlog" on type "Query"
This is what the query looks like for my navigation component. But it throws an error - is there a way to make it just return null?
query NavigationQuery {
allStrapiBlog {
nodes {
title
strapi_id
}
totalCount
}
}
How do I make unsuccessful GraphQL queries not break the build, so I can build a gatsby site with a empty blog?
But it throws an error - is there a way to make it just return null?
Indeed, you need to configure your GraphQL schema to allow nullable fields.
You have a boilerplate that you can tweak to match your data types at https://www.virtualbadge.io/blog-articles/nullable-relational-fields-strapi-gatsbyjs-graphql.
The idea relies on using the createSchemaCustomization API in your gatsbt-node.js to add your own type definitions.
Something like:
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
type StrapiBlogPost implements Node {
title: String!
content: String
thumbnail: File
}
`;
createTypes(typeDefs);
};
In this case, the title is required (because of the !, which means that the type is non-nullable) while content and thumbnail can be null.
Afterward, you will only need to adapt your component to avoid code-breaking logics when null data is fetched.

GraphQL dynamic query strategy best practices

What is a good strategy for dynamically building a query schema for objects and fields with Apollo Client and GraphQL?
We have T-Shirt, Pants, and Shoes objects in our schema. Each of these vary on the types of fields readily available.
There are two input fields, a single entity drop down for TShirt, Pants, and Shoes, and a multi-select drop down to select from the fields available from the schema.
The query schema is produced based on the user's input.
const schema = gql
`query {
tshirt {
logo
brand
}
pants {
length
wasteSize
}
shoes {
lacesStyle
color
}
}
}`
query {
tshirt($logoSkipVal: Boolean! = false, $brandSkipVal: Boolean! = false) {
logo #skip(if: $logoSkipVal)
brand #skip(if: $brandSkipVal)
}
}
I have it working with interpolation manipulation. However, you could imagine as the fields grow in abundance so does the amount of skip directives. Is there maybe a way to use #skip or #include to check if a GraphQL variable with a list of strings includes the field name?
Is there any reason you aren't using Fragments to accomplish this? It seems to be the most applicable solution for combining shared logic between queries and mutations.

Ability to extend all Apollo/GraphQL mutations with same fields. "Generic fragments" wanted

Problem definition
In the project I'm currently working on we're using React with Apollo Client.
On all our mutations, we have the following fields in our response:
ok
errors {
field
messages
}
The back-end extends all mutations with these fields, hence it would be nice to have a good, short way to include these fields on all mutations in the front-end, as well as be able to change this "fragment" in the future.
Hence I'm interested in shortening these same 4 lines into 1 across all my mutations.
What I've tried so far:
I've tried looking into Apollo fragments, however they seem to require a type that the fields are on or "relating to", eg.
fragment NameParts on Person {
firstName
lastName
}
Here, the frament NameParts is created using Person. However, I'm interested in extending ALL mutations.
It would be nice if I could make a generic fragment like so:
fragment OkAndErrors {
ok
errors {
field
messages
}
}
This does not seem to be possible.
I've also tried making a string, and importing it into my mutation like so:
export const OK_AND_ERRORS: string = `
ok
errors {
field
messages
}
`;
import { gql } from "apollo-boost";
import { OK_AND_ERRORS } from "./OK_AND_ERRORS";
export const CREATE_API = gql`
mutation CreateApi($newApi: ApiCreateGenericType!) {
createDrugapi(newDrugapi: $newDrugapi) {
${OK_AND_ERRORS}
(...rest of mutation is omitted for brevity)
}
}
`;
Again, it did not work.
I'm not sure if I can use gql function in a smart way with strings or JSON?
There's also inline fragments but I'm in doubt if it can be used for what I need, and the documentation of inline-fragments in Apollo is scarce.
In essence: Is there a smart way to extend Apollo mutations? Does generic fragments exist?
First of all, fragments aren't limited to Apollo but are part of just regular GraphQL queries. The GraphQL site itself actually has a nice explanation of them: https://graphql.org/learn/queries/#fragments
Essentially we can put fragments onto any query to extract data dependencies, but they're also useful for matching types using their on X type conditions.
In your case, you're saying that each mutation returns a kind of result type that has a common errors field. This tells me that you may have a MutationError kind of type already. However these MutationResult types that all have an errors fields should all implement an interface, if they don't already.
Interfaces are a great tool in the schema language to define explicitly that a type implementing it must always include a certain set of fields, in this case the errors fields. This means that we'd write our results like so:
interface MutationResult {
errors: [MutationError!]
}
type ExampleMutationResult implements MutationResult {
ok: Boolean
errors: [MutationError!]
}
type UserMutationResult implements MutationResult {
user: User
errors: [MutationError!]
}
As you can see above, the MutationResult interface is now implemented by several results, which allows me to write a reusable fragment that can be applied to any type that implements it, e.g.
fragment MutationResultErrors on MutationResult {
errors {
field
messages
}
}
Which I can then start using for all mutation queries that I'm defining. This is more predictable and expected in GraphQL rather than doing some client-side document transformations, string interpolations in a query, or something similar, as it'll be baked into your schema.
Side note: What I'd also say is, I've found that it's commonly seen that people have started to split their mutations into "errors" and "results" and made some kind of union or interface to differentiate between the two. But often they then implement generic errors with messages. It's important to say that errors that don't carry any relational data are actually already baked into GraphQL: https://spec.graphql.org/June2018/#sec-Errors

How are arguments added to GraphQL, do they need to be defined before?

Hi Everyone I am just trying to learn graphql as I am using Gatsby. I want to know does each field in graphql take an argument or does it need to be defined somehow before. So for example if you visit this link graphql search results
https://graphql.org/swapi-graphql?query=%7B%0A%09allPeople%20%7B%0A%09%20%20people%20%7B%0A%09%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20birthYear%0A%20%20%20%20%20%20eyeColor%0A%09%20%20%7D%0A%09%7D%0A%7D%0A
If i wanted to limit people by eye color how would I do that. In the docs it seems easy as you would just do something like people(eyecolor: 'brown') but that doesn't seem possible. Am I missing something? I basically want to do a SQL style search for all people where eye color is brown.
Thanks.
Arguments need to be defined in the schema and implemented in the resolver. If you're consuming a 3rd party API (like the link you provided), you're limited to their schema. You can tell by looking at their schema (by clicking Docs on the right side of the page) which fields take arguments. For example, person takes id and personID arguments:
people doesn't take any arguments, as seen in the schema:
If you're building your own schema, you can add arguments to any field, and when you implement the resolver for that field you can use the arguments for logic in that resolver.
If you're working with a schema that you don't control, you'll have to add filtering on the frontend:
const {people} = data.allPeople;
const brownEyedPeople = people.filter(({eyeColor}) => eyeColor === 'brown');
When you start developing in Gatsby and actually pull your data into Gatsby, there will be a filter query option that automatically becomes available in the query arguments.
https://www.gatsbyjs.org/docs/graphql-reference/#filter
You can expect to be able to filter your people by eyeColor by using the below query:
{
allPeople(filter: { eyeColor: { eq: "brown" } }) {
edges {
node {
id
name
birthYear
eyeColor
}
}
}
}

Is there a way to pass a fragment to graphiql?

It's possible to pass a query, but apparently not a fragment:
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
query: `# Welcome to GraphiQL
query PostsForAuthor {
author(id: 1) {
firstName
posts {
title
votes
}
}
}`}));
Update 10/12/2017
It is possible to send fragments along with a query using Apollo's client:
http://dev.apollodata.com/core/fragments.html
This is not a solution to the original question, however; I would like to pass fragments to a graphiql server instance at startup.
by startup do you mean from the server? if so I don't believe that's how fragments are used. my understanding is as follows:
on the server you provide Types (like User)
on the client you query those Types using queries and fragments
for instance, if you provide type User on the server, on the client graphQL you can use fragments to query that type:
graphQL (client)
fragment authorData on AuthorType{
firstName
posts {
title
votes
}
}
query PostsForAuthor {
author(id: 1) {
...authorData
}
}
As you noticed (and as detailed here) GraphiQL takes a query argument:
query: an optional GraphQL string to use as the initial displayed query, if undefined is provided, the stored query or defaultQuery will be used.
If putting a fragment in as the value for that argument doesn't work, then I don't believe there is any way to start with a fragment ... but really why would you even want to? A fragment by itself isn't executable, and the whole idea is to start GraphiQL with a (executable) query.
If all you want is to be able to copy/paste in some text that you use frequently in your queries, a bookmarklet might be a better idea.

Resources