Skip to content

GraphORM

Lee Hansel Solevilla edited this page Sep 30, 2021 · 7 revisions

Integrating GraphQL and TypeORM together

GraphORM is an internal solution primarily used for translating GraphQL queries to SQL queries. With the help of TypeORM, GraphORM translates a GraphQL AST (Abstract syntax tree) into a SQL query. This SQL uses Postgres’s JSON capabilities to resolve a GraphQL query in a single SQL query that includes subqueries, joins, and everything needed to fetch the relevant information. It uses JSON to create deep hierarchy objects rather than the normalized rows of traditional SQL queries.

Settings

In this file we have our global GraphORM instance that is used across the app. It contains the general configuration for the actual usage of the library.

Types

interface GraphORMType

property type required default comments
from string false the key from the Object where this was defined one example is in GraphORMMapping when defining a new key with value
fields An Object having keys as string and values as GraphORMField false null
requiredColumns string[] false null our GQLDatePageGenerator utilizes createdAt field for pagination, and if you happen to not need that column in your query, hence, not included in your schema, you can define that field here so the query will be able to proceed with no issue

interface GraphORMMapping

An Object having keys as string and values as GraphORMType.

Utilities

GQLDatePageGenerator

Paginated results are very common to lessen the load requested to the server. This PageGenerator requires two generic parameters to be passed. Though we usually utilize type inference and not explicitly define those types.

The first one is a type that must have a property of createdAt: Date as this will be used as a reference for the pagination.

The second one is the type for the parameters to be passed as part of the query itself.

Types

interface GQLDatePageGeneratorConfig

property type required default comments
maxSize number false 100 max size to return per request

interface QueryOptions

property type default comments
queryBuilder (builder: GraphORMBuilder) => GraphORMBuilder undefined this is where you specify your conditions for your query, sorting, etc.
orderByCreatedAt 'ASC' | 'DESC' 'ASC' the pagination is based on the createdAt property, hence, it depends from its actual order

API

constructor

This will accept the configuration and create an instance of your page generator that can be used across the module.

Parameters

index type required default
0 GQLDatePageGeneratorConfig false undefined

function queryPaginated

The method responsible for making your query paginated aligned with GraphQL's requirements

Parameters - most of the required parameters are coming from the GraphQL resolver so you won't have to think about it too much!

index type required comes from the resolver?
0 Context true true
1 GraphQLResolveInfo true true
2 TArgs - the second generic type parameter mentioned in GQLDatePageGenerator's description true false
3 QueryOptions false false
Sample code:
import { GQLDatePageGenerator } from './pageGenerator';

// our GraphQL resolver that is uniform across the app
export const resolvers: IResolvers<any, Context> = {
  Query: traceResolverObject({
    samplePaginatedRequest: async (
      _,
      args: YourQueryArgs,
      ctx,
      info,
      // the required type to return for a paginated query
    ): Promise<ConnectionRelay<YourActualType>> => {
      // where the Page Generator is used
      const pageGenerator = new GQLDatePageGenerator();

      // as you may notice, the only thing we had to manually write is the actual query
      return pageGenerator.queryPaginated(ctx, info, args, {
        queryBuilder: (builder) => {
          builder.queryBuilder = builder.queryBuilder.andWhere(
            `${builder.alias}.postId = :postId`,
            { postId: args.id },
          );

          return builder;
        },
        orderByCreatedAt: 'DESC',
      });
    },
  }),
};

function createPageGenerator

In the constructor, you pass a parameter to which will become the configuration where your page generator will base off from. Whenever you want to change those settings, you can call this function which will accept the same parameters to create another Page Generator containing the new configs.

Parameters

index type required
0 GQLDatePageGenerator false
Sample code:
import { GQLDatePageGenerator } from './pageGenerator';

const pageGenerator = new GQLDatePageGenerator();

// ... somewhere along the way you had to change something on some query

pageGenerator.createPageGenerator({ maxSize: 50 }); // let's say you wanted smaller size to be returned as the query is quite expensive

Note

This library was built in-house, to provide solutions to problems encountered and make developers' experience better. It is still in its early life, so we would love it if you will be able to help us further this documentation in any way possible. If not, that's totally fine! We are already very happy to have you here!