How can I wire up a GraphQL API to RedwoodJS?

I have an app that gets some restaurant data given a zip.

import { Link, routes } from '@redwoodjs/router'
import { useState } from 'react'
import { Form, TextField, Submit } from '@redwoodjs/forms'
import { GraphQLClient } from 'graphql-request'

export const getZipData = async (zip) => {
  const endpoint = `https://....appsync-api.us-east-1.amazonaws.com/graphql`

  const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      'x-api-key': '...',
    },
  })

  const query = gql`query GetZip($zip: String!) {
    get_zip(zip: $zip) {
      zip
      timezone
      restaurants {
        name
      }
    }
  }`

  return graphQLClient.request(query, { zip: zip })
}

const HomePage = () => {
  const [zip, setZip] = useState()

  const onSubmit = (data) => {
    getZipData(data.zip).then(rc => {
      setZip(rc.get_zip)
    })
  }

  return (
    <div>
      <Form onSubmit={onSubmit} style={{fontSize: '2rem'}}>
        <TextField
          name="zip"
          placeholder="Zip code"
          maxLength="5"
          validation={{ required: true, pattern: /^\d{5}$/ }}
        />
        <Submit>Go</Submit>
      </Form>
      <div>
        {zip &&
          <div>
            <h2>{zip.zip}</h2>
            <h3>{zip.timezone}</h3>
          </div>
        }
        {zip && zip.restaurants.map(r =>
          <div>{r.name}</div>
        )}
      </div>
    </div>
  )
}

export default HomePage

What I’d like is to turn it into ZipCell that fetches data. How does one turn this into an SDL?

Hi @dblock! Given that you already have the code above, setting this up on the API side with Service + SDL code should be pretty efficient. Take a look at the “Using a 3rd Party API” Cookbook — specifically the “Server Side API” section:

Let us know how that goes and definitely loop back if you can’t get things to work.

Here’s how I wired up Fauna for GraphQL, should be fairly similar to what you’ve got going on here:

Cell

// web/src/components/PostsCell/PostsCell.js

export const QUERY = gql`
  query POSTS {
    posts {
      data {
        title
      }
    }
  }
`

export const Loading = () => <div>Loading posts...</div>
export const Empty = () => <div>No posts yet!</div>
export const Failure = ({ error }) => <div>Error: {error.message}</div>

export const Success = ({ posts }) => {
  const {data} = posts
  return (
    <ul>
      {data.map(post => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

Page

// web/src/pages/HomePage/HomePage.js

import PostsCell from 'src/components/PostsCell'

const HomePage = () => {
  return (
    <>
      <h1>RedwoodJS+Fauna</h1>
      <PostsCell />
    </>
  )
}

export default HomePage

SDL

// api/src/graphql/posts.sdl.js

import gql from 'graphql-tag'

export const schema = gql`
  type Post {
    title: String
  }

  type PostPage {
    data: [Post]
  }

  type Query {
    posts: PostPage
  }
`

DB

// api/src/lib/db.js

import { GraphQLClient } from 'graphql-request'

export const request = async (query = {}) => {
  const endpoint = 'https://graphql.fauna.com/graphql'

  const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      authorization: 'Bearer <FAUNADB_KEY>'
    },
  })
  try {
    return await graphQLClient.request(query)
  } catch (error) {
    console.log(error)
    return error
  }
}

Service

// api/src/services/posts/posts.js

import { request } from 'src/lib/db'
import { gql } from 'graphql-request'

export const posts = async () => {
  const query = gql`
  {
    posts {
      data {
        title
      }
    }
  }
  `

  const data = await request(query, 'https://graphql.fauna.com/graphql')

  return data['posts']
}

GraphQL Handler

// api/src/functions/graphql.js

import {
  createGraphQLHandler,
  makeMergedSchema,
  makeServices,
} from '@redwoodjs/api'

import schemas from 'src/graphql/**/*.{js,ts}'
import services from 'src/services/**/*.{js,ts}'

import { db } from 'src/lib/db'

export const handler = createGraphQLHandler({
  schema: makeMergedSchema({
    schemas,
    services: makeServices({ services }),
  }),
  db,
})
2 Likes

@ajcwebdev This is a really great example! Bookmarking so I’ll be able to direct people here as needed :+1:

@ajcwebdev Indeed! I was able to do this for my own example, https://github.com/dblock/redwood-js-appsync-graphql-demo

Very cool, I’ve been hearing a lot about AppSync recently and have been interested in checking it out so this is perfect.