Problem(s):
-
I want to create multiple API(s), however, I don't want the consumers to have the need to call n different URL(s).
-
I want to empower my developers/consumers to decide what they need, so that I don't have to return all the data corresponding to an API. My mobile clients want to request lesser data in a request than the web clients.
-
I want the solution to be cost effective, yet I should be able to scale and meet high demands.
-
I want to have one gateway for different API(s). I would be creating multiple microservices eventually.
Solution:
Since, I am at the beginning of a project and hence to solve the problem 1, 2 and 4, I decided to use
GraphQL as GraphQL allows to describe the data and empowers the clients to get exactly what they need. Typically, we would need to define:
-
GraphQL Types to describe our data
-
Resolvers: the function(s) which makes the actual call and populates the requested data.
To make the solution cost effective, I chose azure functions. Here is how, I completed the solution:
Pre-requisites:
The How to steps:
-
Create a function app by running the command in the commandline:
func init graphql-azure --worker-runtime node
This will create a folder graphql-functions and a function app inside that.
-
Go to the folder you created above:
cd graphql-azure
-
Install npm packages:
npm i --save apollo-server-azure-functions graphql
-
Create an HTTP Trigger based function.
func new --template "Http Trigger" --name graphql
This will create a folder graphql. Checkout the function.json. Replace that with the code:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
Notice the $return in the above code, this is required to return the GraphQL results.
-
Since, we are focused on setting up graphql, let's assume that we are connecting to another api which returns the data. So, I created a file data.js in the folder graphql and added the data.
const users = [
{
"id": 1,
"name": "Gaurav",
"age": "30"
},
{
"id": 2,
"name": "Sunny Setia",
"age": "36"
},
{
"id": 2,
"name": "Sunny Vohra",
"age": "33"
},
{
"id": 3,
"name": "Nitin Verma",
"age": "35"
}
];
module.exports = {users};
-
Create another file graphqlTypes.js and add your graphQL types there. This is how you describe your data.
const { gql } = require('apollo-server-azure-functions');
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
type Query {
hello: String
books: [Book]
users: [User]
}
type Book {
title: String
author: Author
}
type Author {
name: String
books: [Book]
}
type User {
id: Int
name: String
age: String
}
`;
module.exports = {
typeDefs,
gql
};
-
Create a file named graphqlQuery.js and add the following code:
const { users } = require('./data');
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => 'Hello world!',
books: () => {
return [
{
"title": "The Trusted Advisor",
"author": {
"name": "Gaurav Madaan"
}
},
]
},
users:() => {
return users;
}
},
};
module.exports = {resolvers};
Here we are adding the actual resolvers, which helps in populating the requested data.
-
Now, update your index.js with the following code:
// Import Apollo Azure integration library
const { ApolloServer } = require('apollo-server-azure-functions');
const { typeDefs } = require('./graphqlTypes');
const { resolvers } = require('./graphqlQuery');
const server = new ApolloServer({
typeDefs
, resolvers
, introspection: true
, playground: true
});
exports.graphqlHandler = server.createHandler();
-
In the Terminal/commandline, run the following command:
func host start
-
Yay! Your GraphQL server should be running at http://localhost:7071/api/graphql
- Here is the source on github https://github.com/codestellar/javascript-azure-samples/tree/main/graphql-azure