DEV Community

Cover image for Simple GraphQL Node Interface implementation
Sibelius Seraphini for Woovi

Posted on

Simple GraphQL Node Interface implementation

Node interface is a GraphQL pattern that unfortunately is not in most GraphQL schemas.
You can understand the benefits of the Node reading The magic of the Node interface.
Node simplifies a lot your GraphQL schema because it lets you fetch or refetch any type of your GraphQL schema by the Global ID.

Node Interface

query SearchDetail($id: ID!) {
  search: node(id: $id) {
    __typename
    ... on User {
      name
    }
    ... on Company {
      name
    }
    ... on Customer {
      name
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The node interface gives you the capability to get information from any GraphQL type in your schema that implements the node interface.
You just need a global ID and it will fetch the correct type for you.

Imagine you are building a search detail screen that will receive a global ID and needs to render specific data based on the ID type, how would you build that? If you are using GraphQL and it has the node interface implemented, you can just ask for specific information per each type.

Usually a Global ID is like this base64Encode(${GraphQLObjectTypeName}${ID})

Naive Implementation

A naive implementation of the node interface would look like this

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

const idFetcher = async (globalId: string, context: GraphQLContext) => {
  const { id, type } = fromGlobalId(globalId);

  if (type === 'User') {
    return UserModel.find(id);
  }
  // many ifs...
  // all the loads of your project
...

  return null;
};

const typeResolver = object => {
  if (obj instanceof User) {
    return UserType;
  }
  // many ifs...
  // all the types of your project
...

  return null;
}

const { nodeField, nodesField, nodeInterface } = nodeDefinitions(
  idFetcher,
  typeResolver,
);
Enter fullscreen mode Exit fullscreen mode

Following this approach, your node interface code will have as many ifs as types. A huge file in a big GraphQL Schema.

Type Register approach

const typesLoaders: TypeLoaders = {};

const registerTypeLoader = (type: GraphQLObjectType, load: Load) => {
  typesLoaders[type.name] = {
    type,
    load,
  };

  return type;
};

const idFetcher = (globalId, context: GraphQLContext) => {
  return typesLoaders[fromGlobalId(globalId).type](context, id)
};

const typeResolver = (obj) => {
  return typesLoaders[obj.__typename].name;
};
Enter fullscreen mode Exit fullscreen mode

In this approach, we register one load function to each type that we have in our GraphQL Schema.
It is a distributed approach instead of a centralized approach.
Each Type registers its load function.

In Conclusion

If you are not using GraphQL, you should consider giving it a try.
GraphQL simplifies a lot of backend and frontend code.
If your GraphQL does not have a node interface, consider adding it to it to simplify and reduce the number of fields in the Query root type.


Woovi
Woovi is a Startup that enables shoppers to pay as they like. Woovi provides instant payment solutions for merchants to accept orders to make this possible.

If you want to work with us, we are hiring!

Top comments (1)

Collapse
 
daniloab profile image
Danilo Assis

Node Interface is awesome!