GraphQL-Relay - Using nodeDefinitions

GraphQL Logo

This section is about using graphql-relay-js with sequalize-relay.


This guide aims to help explain how to connect to nodeDefinitions with sequelize.

Setting up relay nodes:

We can use nodeDefinitions from graphql-relay-js in conjunction with sequelize helpers to setup the node definition. This setup does not need the sequelize-relay library.

What we need to do is wire up a sequelize model to the nodeDefinitions function.

import the modules:

import {
  nodeDefinitions,
  fromGlobalId
} from 'graphql-relay-js';

I have personally used the following boilerplate to setup the nodeDefinitions. I welcome other implementations, but the first step for me is to copy and paste the following code into the schema file

nodeDefinitions boilerplate:

/**
 * We get the node interface and field from the relay library.
 *
 * The first method is the way we resolve an ID to its object.
 * The second is the way we resolve an object that implements 
 * node to its type.
 */
var {nodeInterface, nodeField} = nodeDefinitions(
  (globalId) => {
    var {type, id} = fromGlobalId(globalId);
    switch (type) {
    // we will use sequelize to resolve the id of its object
      default:
        return null;
    }
  },
  (obj) => {
    // we will use sequelize to resolve the object tha timplements node
    // to its type.
    switch (obj.type) {
      default:
       return null;
    }
  }
);

You can quickly setup sequelize by following this guide or by reading the sequelize "GettingStarted" Guide._

Consider a sequelize model called person with the code below:

models/Person.js


module.exports = function (sequelize, DataTypes) {

  var Person = sequelize.define('Person', {
    address: {
      type: DataTypes.STRING,
      description: 'Physical address of the person.'
    },
    email: {
      type: DataTypes.STRING,
      description: 'Email address',
      validate: {
        isEmail: true
      }
    },
    givenName: {
      type: DataTypes.STRING,
      description: 'Given name. In the U.S., the first name of a Person. ' +
      'This can be used along with familyName instead of the name property.'
    }
  });
  return Person;
};

To connect with nodeDefinitions, we need to add virtual types to our sequelize model schema:

Add personType VIRTUAL to the model

This adds a field without putting it in the SQL table

type: {
  type: new DataTypes.VIRTUAL(DataTypes.STRING),
  get() {
    return 'personType';
  }
}

models/Person.js with type added


module.exports = function (sequelize, DataTypes) {

  var Person = sequelize.define('Person', {
    type: {
      type: new DataTypes.VIRTUAL(DataTypes.STRING),
      get() {
        return 'personType';
      }
    },
    address: {
      type: DataTypes.STRING,
      description: 'Physical address of the person.'
    },
    email: {
      type: DataTypes.STRING,
      description: 'Email address',
      validate: {
        isEmail: true
      }
    },
    givenName: {
      type: DataTypes.STRING,
      description: 'Given name. In the U.S., the first name of a Person. ' +
      'This can be used along with familyName instead of the name property.'
    }
  });
  return Person;
};

By adding the type field returning personType - we can then wire it up to nodeDefinitions like so:

nodeDefintions Update

/**
 * We get the node interface and field from the relay library.
 *
 * The first method is the way we resolve an ID to its object.
 * The second is the way we resolve an object that implements 
 * node to its type.
 */
var {nodeInterface, nodeField} = nodeDefinitions(
  (globalId) => {
    var {type, id} = fromGlobalId(globalId);
    switch (type) {
      case 'Person':
        return Person.findByPrimary(id);
      default:
        return null;
    }
  },
  (obj) => {
    // we will use sequelize to resolve the object tha timplements node
    // to its type.
    switch (obj.type) {
      case 'personType':
        return personType;
      default:
       return null;
    }
  }
);

Import more libraries

At the top of the file, we want to import other libraries that will be in use by queryType and personType, as well as connection helpers.

import {
  GraphQLObjectType,
  GraphQLSchema,
  GraphQLString,
  graphql,
} from 'graphql';


import {
  nodeDefinitions,
  fromGlobalId,
  globalIdField,
  connectionFromPromisedArray,
  connectionArgs,
  connectionDefinitions,
} from 'graphql-relay';

import {
  getModelsByClass,
  resolveArrayData,
  getArrayData,
  resolveArrayByClass,
  resolveModelsByClass
} from 'sequelize-relay';

Define Person and personType

Well the code above doesnt explain where Person or personType is coming from. This shall be demystified now:

  • Person is the Model Class that we created earlier from Person.js
  • personType is a GraphQL type schema that needs to be created.

Adding person

import { Person } from './models';

Adding personType


var personType = new GraphQLObjectType({
  name: 'Person',
  description: 'A Person',
  fields: () => ({
    id: globalIdField(),
        address: {
      type: GraphQLString,
      description: 'Physical address of the item.',
      resolve: person => person.address
    },
    email: {
      type: GraphQLString,
      description: 'Email address',
      resolve: person => person.email
    },
    givenName: {
      type: GraphQLString,
      description: 'Given name. In the U.S., the first name of an Person.',
      resolve: person => person.familyName
    }
  }),
  interfaces: [nodeInterface] // <-- Hooking up the nodeInterface
});

add Connection

The connection methods below are also in the Using connections Guide.

var {connectionType: personConnection} =
  connectionDefinitions({nodeType: personType});

queryType

var queryType = new GraphQLObjectType({
  name: 'Query',
  fields: () => ({
    people: {
      description: 'People',
      type: personConnection,
      args: connectionArgs,
      resolve: (root, args) =>
        connectionFromPromisedArray(resolveArrayByClass(Person), args)
    }
    node: nodeField
  })
});

The connection methods shown above are explained further in the Using connections Guide.

GraphQL Query

You can now use the node like so:

query PersonRefetchQuery {
 node(id: "UGVyc29uOjI=") {
  id
  ... on Person {
    id
    givenName
    email
    address
  }
}

returns =>


  data: {
    node: {
      id: 'UGVyc29uOjI=',
      email: '[email protected]',
      honorificPrefix: 'Miss',
      honorificSuffix: 'DVM',
      jobTitle: 'Lead Creative Executive',
      telephone: '718-964-7388 x29503',
      givenName: 'Amir',
      familyName: 'Schmeler',
      address: '197 Mina Gardens'
    }
  }

Look at the test-specs here to see how this works without brevity.

results matching ""

    No results matching ""