Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 25, 2021 09:19 am GMT

TIL: How to use GraphQL variables to give my queries type safety

One of the things I love about GraphQL is how straightforward it is to get up and running with little to no experience. Using a browser-based GraphiQL interface such as the GraphiQL explorer provided by Contentful you can inspect your schema right there in the browser, and construct your queries in no time. But how can you make sure your GraphQL queries are safe from nasties? Lets find out.

To inspect your schema in Contentfuls GraphiQL interface and construct a GraphQL query, enter this URL in your browser, and swap out the SPACE_ID for your Contentful space ID, and ACCESS_TOKEN for your Contentful Delivery API Key.

https://graphql.contentful.com/content/v1/spaces/{SPACE_ID}/explore?access_token={ACCESS_TOKEN}

Make an HTTP POST request with your programming language of choice and boom youve got data.

This is an example of a query that we can use to request data from a single blog post by slug. Notice how were using a where clause to filter the items by a slug that matches a string we supply.

{  blogPostCollection(where: {slug: "what-is-a-rest-api"}) {    items {      slug      title      excerpt      readingTime    }  }}

And heres the data we get back.

A screenshot of the GraphiQL explorer showing a query made using a string in the where clause, and the data successfully returned.

Heres how we can make the same request using JavaScript fetch (and no external dependencies!).

const query = `{  blogPostCollection(where: {slug: "what-is-a-rest-api"}) {    items {      slug      title      excerpt      readingTime    }  }}`;const response = await fetch(  `https://graphql.contentful.com/content/v1/spaces/${SPACE_ID}/environments/master`,  {    method: "POST",    headers: {      Authorization: `Bearer %ACCESS_TOKEN%`,      "content-type": "application/json",    },    body: JSON.stringify({ query }),  },).then((response) => response.json());console.log(response);

All of this is great, and perfectly valid GraphQL. And, if youre using a static site generator such as Next.js, Gatsby or Nuxt which will pre-render your pages at build-time and serve static pages to the client, you should be good to go. Id been doing this for months using Contentfuls GraphQL API to fetch my data to power my personal website built with Next.js.

However, whilst queries like this are super-fast to write and get your projects out fast what if youre making GraphQL queries dynamically on the client and not as part of a static site build? What if someone could play around with your data in real-time by inserting an incorrect data type, a GraphQL mutation or similar instead of a string?

Heres where GraphQL variables save the day!

Its worth mentioning that because the Contentful GraphQL API is read-only, this kind of scenario wont happen but security considerations are always good to bear in mind regardless. Lets take a look!

Use GraphQL variables for type safety and self-documenting queries

GraphQL variables offer an extra layer of protection in your queries, namely type safety meaning that a query will only accept dynamic variables of certain data types, such as String, Int (number), DateTime and so on. And whats more, there isnt much more work needed to make your GraphQL queries safer!

To use variables in your GraphQL queries:

  1. Create what looks like a traditional function prefaced by the word query. You can name this query function whatever you like. Ive named mine GetBlogPostBySlug.
  2. Inside the parentheses of the function declaration, name and define the types of the variables the query will accept, and prefix your variable names with a $. The query below will accept a variable named $slug, which is of type String. The bang or exclamation mark that comes after the type name means that it is a required variable for the query to execute.
  3. In an HTTP POST request to the GraphQL API, variables are passed to the GraphQL request as a separate property inside the body of the request. Click on the query variables pane at the bottom of the GraphiQL explorer. Create an object, and add your stringified variable name and value as key: value (its important to stringify the key name here!).

A screenshot of the GraphiQL explorer showing the slug variable used correctly, passed in via a separate query variables tab, and the data returned is the same as the previous query.

Lets look at an example of using GraphQL variables using JavaScript fetch. Notice how we have replaced the original query with the function-style query from above, and have created a variable named variables that we pass into the body of the HTTP request.

const query = `query GetBlogPostBySlug($slug: String!) {  blogPostCollection(where: {slug: $slug}) {    items {      slug      title      excerpt      readingTime    }  }}`;const variables = { slug: "what-is-a-rest-api" };const response = await fetch(  `https://graphql.contentful.com/content/v1/spaces/${SPACE_ID}/environments/master`,  {    method: "POST",    headers: {      Authorization: `Bearer %ACCESS_TOKEN%`,      "content-type": "application/json",    },    body: JSON.stringify({ query, variables }),  },).then((response) => response.json());console.log(response);

And thats how I learned to make my GraphQL queries type-safe and free from nasty attacks on dynamic API calls!

Going further with more types

There are a variety of different variable data types available on Contentfuls GraphQL API. As well as the standard data types such as String, Int and DateTime, you can also pass variables to a query that are entry-specific and API-specific.

To inspect the types available on your schema, click on the Docs links at the top right of the GraphiQL explorer:

A screenshot of the GraphiQL explorer, showing the docs button a the top right highlighted.

Click on Query:

A screenshot of the GraphiQL explorer, showing the docs tab open and the root types  query area highlighted.

And find the content type youd like to inspect.

A screenshot of the GraphiQL explorer, showing the query tab open to inspect the scheme, with the type order: EventOrder highlighted.

Another thing I learned on this journey is that you cant use variables in GraphQL for everything namely keys in WHERE clauses.

I recently created a GraphQL query to fetch the events on my website. On the main events page, I wanted to show future events in ascending order, and on the past events page, events in descending order.

The two supported variables involved in this query are:

  • $order date_ASC or date_DESC
  • $date as an ISO string

But I also needed a third dynamic variable which was to control whether the API returned events before (date_lt date less than) or after (date_gt date greater than) a particular date. Unfortunately, this part of a GraphQL query cannot be controlled with a variable, and so I had to be creative and pass in a calculated string to the query like so:

// https://github.com/whitep4nth3r/p4nth3rblog/blob/main/contentful/Events.jsimport ContentfulApi from "@contentful/Api";const defaultOptions = {  future: true,};/* * Get all events -- future by default */static async getEvents(options = defaultOptions) {  // Calculate date_ASC for future events, or date_DESC for past events  const order = options.future ? "date_ASC" : "date_DESC";  // Generate today's date  const date = new Date();  // And format it to an ISO String  const formattedDate = date.toISOString();  // Decide on the date filter to pass in as a string  const dateFilter = options.future ? "date_gt" : "date_lt";  // Construct variables object to send with the HTTP POST request  const variables = { date: formattedDate, order };  // Build the query  const query = `query GetEvents($date: DateTime!, $order: [EventOrder]!) {    eventCollection(where: {${dateFilter}: $date}, order: $order) {      items {        sys {          id        }        date        name        link        description        timeTbc        isVirtual        image {          url          description          height          width        }      }    }  }`;  // Call out to the base API call  const response = await this.callContentful(query, variables);  const eventCollection = response.data.eventCollection.items    ? response.data.eventCollection.items    : [];  return eventCollection;}

One other thing to notice is that the $order variable is of type EventOrder, which we saw when we inspected the schema above, which is an API and entry-specific type!

So there you have it. Fancy and safe GraphQL queries, so you can build great stuff with the Contentful GraphQL API without worrying. You can check out the code on GitHub for the full range of queries I make with GraphQL on my website, and if youre curious about GraphQL and want to learn more, you can learn along with Stefan Judis React and GraphQL video course in our developer portal. Happy querying, friends!


Original Link: https://dev.to/whitep4nth3r/til-how-to-use-graphql-variables-to-give-my-queries-type-safety-3m4h

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To