Implementing GraphQL When 3rd Party APIs Aren’t Flexible Enough

Writing Code

We often depend on third-party APIs that do not necessarily have the flexibility we require from modern APIs. One solve for this problem is to add a new layer on top of the third-party API. A simple and flexible solution is proxying the third party API using GraphQL. Learn more about Axonize’s 5 core technologies here.

Some brief advantages of GraphQL include:
  1. Better query efficiency – GraphQL allows you to get from a number of different entities in one query.
  2. No overfetching with GraphQL – GraphQL allows access to an arbitrary set of data exposed by the server. You specify what you need and will get this data (and only this data) in one trip to the server.
  3. Speed of development
  4. Documentation by default
  5. Strong type system – Given a query, tooling can ensure that the query is both syntactically correct and valid within the GraphQL type system before execution, i.e. at development time, and the server can make certain guarantees about the shape and nature of the response. This makes it easier to build high-quality client tools.

The most common way to run a GraphQL API server is with Express, a popular web application framework for Node.js. You’ll need to install two additional dependencies:

npm install express express-graphql graphql --save

For example, we will proxy the Axonize API with GraphQ, We’ll wrap up the GET  “devices” resource for the simple case. The Axonize API documentation is here.

We will create a new file called server.js and insert the following code into it:

const express = require('express');
const schema = require('./scema');

const app = express();

app.use(
    '/graphql',
    graphqlHTTP({
      schema,
      graphiql: true,
    }),
  );
  
app.listen(port, () => {
  console.log(
    'GraphQL Server started successfully on port %s',
    port,
  );
});

This is a basic GraphQL server. As of now, the code cannot run because we haven’t written a schema. To set up our schema, we’ll create a new file called schema.js and enter the following code:

const deviceType = require('./devices');

const { GraphQLSchema, GraphQLObjectType } = require('graphql');

const queryType = new GraphQLObjectType({
  name: 'AxonizeQuery',
  description: 'The base level of Axonize API',
  fields: {
    devices: deviceType,
  },
});

module.exports = new GraphQLSchema({
  query: queryType,
});

We have set up our server’s main schema, declaring all of the entities we want to publish. Next, we’ll create the schema of the entity “device.” In this schema, we’ll map all of the fields we want to reveal via GraphQL. We’ll create a new file called device.js and write the following definition:

const {
  GraphQLObjectType,
  GraphQLList,
  GraphQLID,
  GraphQLString,
  GraphQLBoolean,
  GraphQLInt,
} = require('graphql');

const  getDevices; // Need to implement

const type = new GraphQLObjectType({
  name: 'Device',
  description: 'Axonize Device entity',
  fields: {
    id: {
      type: GraphQLID,
      description: 'The device ID',
    },
    appId: {
      type: GraphQLString,
      description: 'The application ID',
    },
    name: {
      type: GraphQLString,
      description: 'Device name',
    },
    productId: {
      type: GraphQLString,
      description: 'Device prodcut ID',
    },
    isConnected: {
      type: GraphQLBoolean,
      description: 'Device Connection status ',
    },
    isAlarmed: {
      type: GraphQLBoolean,
      description: 'Device alarm status ',
    },
    lastReadings: {
      type: new GraphQLList(
        new GraphQLObjectType({
          name: 'DeviceLastReadings',
          description: 'Device Last Readings',
          fields: {
            type: {
              type: GraphQLInt,
            },
            name: {
              type: GraphQLString,
            },
            value: {
              type: GraphQLString,
            },
          },
        }),
      ),
      description: 'Device alarm status ',
    },
  },
});

module.exports = {
  type: new GraphQLList(type),
  resolve: getDevices,
};In this example, we did not map all the fields we have in the entity, but only the following: id - string appId - string name - string productId - string isConnected - bool isAlarms - bool lastReadings - array of object with type, value and name fields.

The last thing to do is implement the getDevices function, which calls to a third-party API to fetch the data from it. For the sake of simplicity, we will use axios to send API requests. We’ll install it using the command:

npm install axios

Then, we’ll create the getDevices function:

const getDevices = (e, r, req) => {
  const url = 'https://api.axonize.com/odata/devices?$top=15';
  
  const { authorization, appid } = req.headers;

  const headers = {
      authorization,
      appid,
    };

  return axios
    .get(url, {
      headers,
    })
    .then(res => res.data.value);
};

As evidenced, we’re sending the authorization headers that the API requires to authenticate the user. Now we’re done, and you can run the server with the command:

node server.js

Going forward we can simply begin to execute queries on the GraphQL layer we’ve just created. Feel free to contact us here with any questions.

Video example of querying the graphQL layer

envelope-subscribe-icon
Don't miss out on the latest
Get notified on Industry updates. We promise not to spam