GraphQL and NodeJS integrations using Cloud Code Functions

GraphQL and NodeJS integrations using Cloud Code Functions

GraphQL brings sugar, spice, and everything nice to API developers, but it is basically a query language so you can specify what you are looking for.

What if you need more business intelligence than that in your application?

What if you need some logic along with it?

What if you want that neat NPM Module module along with it?

Well, fasten your seat belts because today I’ll show you something very powerful. And with great powers, comes great… well… great time savings, great possibilities, great lots of good stuff…

 

If you want to know more about GraphQL take a look at this post: What is GraphQL

You must be this tall to ride…

And use Parse 3.5.0 or higher to play with GraphQL.
Go to Server Settings and Manage Parse Server and make user you’re using a compatible version.

 

Our brand new shiny feature: GraphQL + Cloud Code Functions

 

If you are a Parse/Back4app user already, you probably have used or at least heard about Cloud Code.

Cloud Code is essentially NodeJS code that runs from the Back4app’s Applications servers instead of the end devices.

This brings a few key advantages depending on your needs, but essentially it lets you to:

  • Save up on cellphone batteries

    When you take the heavy load of processing out of the device to the Cloud, the intense processing won’t be done on the device, saving up on battery. You get your processing done on our servers and retrieve only the final result to the client. No more hot cellphone in your pocket. No more “OMG this app sucks my battery dry!”.

 

  • Save up on data plans

    So you have a ton of objects that you must retrieve in order to get a report. Thousands? Millions?
    That is a lot of data that you must retrieve and if you’re not on WiFi, you better get that cellphone data plan upgrade.
    We all know data plan is quite expensive (nobody pays for SMS messages anymore, right?) so, what if we had a smarter approach?
    What if we could get the report fully calculated on the cloud and retrieve only the very last result to the device? A smaller payload that would consume so much less from your data plan and also run faster?
    Sounds awesome? That’s what Cloud Code does…

 

  • Get quicker code deploy

    Once upon a time developers had to republish their software to the App Stores. That used to be a lottery back then: get a faster reviewer and your App would be available for users on the same day. Get a slower or picky reviewer and your App could take weeks to be published. If it was published.
    Why risking that?
    Deliver only the frontend part of your Application to the App Stores and leave as much logic as possible to be called as Cloud Code.
    Need to make a small change to the logic? Or a huge one? No problem.
    Change the Cloud Code, deploy it again and you’re as good as new. No reviews from some guy from somewhere else and instant availability for your clients.

 

But again… what about GraphQL?

GraphQL lets you make queries. You can make very smart queries, but just queries.

When our CEO, Davi, was discussing how to make it smarter, the integration with Cloud Code Functions appeared to be just logic: you have the very best of both worlds! The power and intelligence of Cloud Code Functions, AND, the easiness and maintainability of GraphQL.

Trough our new feature you can extend the types of GraphQL to execute Cloud Code Functions and retrieve its results.

You can apply any business logic you can possibly imagine on your Cloud Code Functions, include along NPM Modules with it and query it all with GraphQL.

Enough talking. Let’s get our hands on it…

 

The Classes and Objects we will use

For this post, I created two distinct classes: Employee and Pet, that will hold the employees here at Back4app and their respective pets.

An Employee has the following properties:

  •  name (String)
  • age (Number)
  • email (String)
  • position (String)
  • hasThisPet (Pointer to the Pet class)

screen-shot-2019-08-07-at-13-18-26

A Pet has the following properties:

  • name (String)
  • species (String)

screen-shot-2019-08-07-at-13-18-37

And some Cloud Code Functions

And for our Cloud Code Functions, I will write a file named main.js and include the following code.

It has five fully commented Cloud Code Functions that will do:

  • checkGraphQLSupport
    retrieve if the App has support to GraphQL
  • retrieveFirstEmployeeByName
    retrieve all details of the first Employee found on the database with a given name
  • retrieveAllEmployees
    retrieve all details about all the Employees
  • retrieveOnwerOfPetByName
    retrieve the details of an Employee that has a Pet with a given name
  • retrieveEmployeeByNameWithPet
    retrieve all the details of an Employee and its Pet
Parse.Cloud.define("checkGraphQLSupport", async req => {
  /*
    This function returns if the App has support for GraphQL. 
    The parseGraphQLServer is true when the App has support, or false otherwise
  */
  if (parseGraphQLServer){
    return "This App has GraphQL support.";
  } else {
    return "This App does not have GraphQL support. Wrong Parse version maybe?";
  }
});

Parse.Cloud.define("retrieveFirstEmployeeByName", async req => {
  /*
    This function retrieves the first Employee found with a given name.
    All properties of the Employee are retrieved.
    Only one Employee is returned if there are more than one in the Database.
    If there are no Employees, null is retrieved.
  */
  const query = new Parse.Query("Employees"); 
  query.equalTo("name", req.params.name);
  const result = await query.first();
  return result;
});

Parse.Cloud.define("retrieveAllEmployees", async req => {
  /*
    This function retrieves all the Employees.
    All properties of the Employee class are retrieved, but that class only.
    No details of Pointers or Relations are retrieved, only the objectId.
    An array of Employees is returned. Empty if no Employees.
  */
  const query = new Parse.Query("Employees"); 
  const results = await query.find();
  return results;
});

Parse.Cloud.define("retrieveOnwerOfPetByName", async req => {
  /*
    This function retrieves the information about the Employee related to an Pet,
    by the name of the Pet.
    All properties of the Employee class are retrieved.
    No details of the Pet will be retrieved.
    An array of Pet is returned. Empty if no Pet is found.
  */

  // First we make a query to retrieve the information about the Pet
  const petQuery = new Parse.Query("Pet"); 
  petQuery.equalTo("name", req.params.name);
  
  // Then we make a query to retrieve the details of its onwer based on the hasThisPet property
  let employeeQuery = new Parse.Query("Employees"); 
  employeeQuery.matchesQuery("hasThisPet", petQuery);
  const results = await employeeQuery.find();

  return results;
  
});

Parse.Cloud.define("retrieveEmployeeByNameWithPet", async req => {
  /*
    This function retrieves the information about the Employee and its related Pet,
    by the name of the Employee.
    All properties of the Employee class and the Pet class are retrieved.
    An array of Employee is returned, including a fully populated hasThisPet property
    with the information about the pet.
    An empy array is returned if no Employee is found.
  */
  const query = new Parse.Query("Employees"); 
  query.equalTo("name", req.params.name);
  query.include("hasThisPet")
  const results = await query.find();
  return results;
});

We will upload it to our Cloud Code Functions, into the Cloud folder.

 

A little extra step

The Cloud Code Functions we just published can now be used, but in order for them to work with GraphQL, we must create a file named schema.graphql and expose those functions.

The syntax is very simple, yet, needs attention:

extend type Query {
  GraphQLMethodName (parameterName: parameterType): ReturnType! @resolve(to: "CloudCodeFunctionName")
}

for the code above, the syntax represents:

  • GraphQLMethodName
    This is the name that you will call in your GraphQL query. It does not have to match the Cloud Code Function name, but you should choose something that makes it easy to understand what that method does.
  • parameterName
    The name of the parameter that you will consume in the Request when inside the Cloud Code Function. You don’t have to pass this if not using parameters on your Cloud Code Function.
  • parameterType
    The type of the parameter you are passing. You can learn more about it here and see all the possibilities. You don’t have to pass this if not using parameters on your Cloud Code Function.
  • ReturnType
    This is the return type of your method. You can learn more about it here and see all the possibilities.
  • CloudCodeFunctionName
    This must match the Cloud Code Function name that you gave in your main.js file, as it will call that code by function name.

So, for our main.js file we just created, our schema.graphql would be:

extend type Query {
  checkGraphQLSupport: String! @resolve(to: "checkGraphQLSupport")
  retrieveThisEmployeeByName (name:String): EmployeesClass! @resolve(to: "retrieveFirstEmployeeByName")
  giveMeAllEmployees: [EmployeesClass!]! @resolve(to: "retrieveAllEmployees")
  whichEmployeeIsOnwerOfThisPet (name:String): [EmployeesClass!]! @resolve(to: "retrieveOnwerOfPetByName")
  gatherEmployeeAndPetByEmployeeName (name:String): [EmployeesClass!]! @resolve(to: "retrieveEmployeeByNameWithPet")
}

Not that hard, is it?

Notice I have used very extensive names that do not match the Cloud Code Functions name just so you know you can rename when exposing.

Now go back to the Cloud Code Functions section of your App and upload that file as well. Make sure it is also in the Cloud folder. You can drag and drop it there if needed.
If you already have a file with that name in there and cannot upload a new one, you can right-click it and delete before uploading.

Deploy everything and we are ready to go:

screen-shot-2019-08-07-at-14-52-49

 

 Now, time for the magic…

Go to your GraphQL console. Start typing “query” and use the Autocomplete function (CTRL + Spacebar on Windows, OPTION + Spacebar on Mac), and see the magic happen:

screen-shot-2019-08-07-at-15-11-36

 

All our methods are there and we can query each one of them. Let’s try it one by one:

  • checkGraphQLSupport

    (resolves to our Cloud Code Function checkGraphQLSupport)
    screen-shot-2019-08-07-at-15-14-49

 

  • retrieveThisEmployeeByName (name:String)

    (resolves to our Cloud Code Function retrieveFirstEmployeeByName)
    screen-shot-2019-08-07-at-15-19-18

 

  • giveMeAllEmployees

    (resolves to our Cloud Code Function retrieveAllEmployees)
    screen-shot-2019-08-07-at-15-21-06
    Notice on the example above that the name and age properties were retrieved correctly, but the hasThisPet has null values for name and species of the Pet.
    This is due to the fact that in that Cloud Code Function we did not include (using the include() method) the information about the Pet.
    Autocomplete will show us the possibilities, but no data for fulfilling that information was provided on the Cloud Code Function.
    See the gatherEmployeeAndPetByEmployeeNameresolves example below to see how to include information.

 

  • whichEmployeeIsOnwerOfThisPet

    (resolves to our Cloud Code Function retrieveOnwerOfPetByName)
    screen-shot-2019-08-07-at-15-26-12

 

  • gatherEmployeeAndPetByEmployeeName 

    (resolves to our Cloud Code Function retrieveEmployeeByNameWithPet)
    screen-shot-2019-08-07-at-15-28-54

Your awesome definitions were updated 🤯

Now, THAT’S how you bring some business logic to GraphQL.

Love you 3000!

 

Conclusion

GraphQL is a powerful and easy multiplatform query language and runtime, but at the end of the day, it is a Query Language only.
With this brand new integration with Cloud Code Functions, we brought you the very best of both worlds, unleashing the power of Cloud Code (including NPM Modules, baby!).

Now it’s up to you and your creativity! Let us know how you like it and how are you using it in your projects in the comments below!

 


Leave a reply

Your email address will not be published.