0.1.0 • Published 6 years ago

graphql-cursor-sql-helper v0.1.0

Weekly downloads
1
License
MIT
Repository
github
Last release
6 years ago

GraphQl cursor SQL pagination helper for relay compatible schema

:purple_heart: :blue_heart: :purple_heart: Made with Love by Kuba Svehla :purple_heart: :blue_heart: :purple_heart:

Motivation

This library is the extension of awesome graphql-relay-js which solve problem how simply implement cursor pagination to your SQL's dbs query without special magic.

If you're creating GraphQl schema which is compatible with relay cursor pagination (cursor pagination spec ). You probably use graphql-relay-js library for helper functions to define your schema.

Problem with graphql-relay-js is that functions like connectionFromArray(...) works on application javascript layer. That means that process of pagination is inefficient and it takes too much RAM & CPU power.

This library solve how to recalculate Pagination args (first & after & last & before) to SQL's OFFSET LIMIT params.

Another benefits

We added totalCount field to graphQl schema. At the moment graphql-relay-js does not implement it yet. We decided that totalCount is productive for and you have option to set it.

Why is not totalCount in graphql-relay-js (issue)

If you want to enable totalCount you have to set it to your connectionDefinition like in example:

connectionDefinitions({
  name: 'User',
  nodeType: UserType,
  // adding connectionFields to type
  // is necessary for querying totalCount in graphQl
  connectionFields: {
    totalCount: { type: new GraphQLNonNull(GraphQLInt) }
  }
}).connectionType,

note1: connectionField param of connectionDefinition is not documented in readme yet. But you can find implementation here: implemenation of connectionFields in relay-graphql-js

note2: first param is meaning last added nodes -> not first positions in array

So if you select

first 3 items from 50 it generate:

  • offset: 0
  • limit: 3

last 3 items from 50 it generate:

  • offset: 47
  • limit: 3

Instalation

yarn add graphql-cursor-sql-helper

or

npm install graphql-cursor-sql-helper

API

library provide this function:

  • connectionToSqlQuery

connectionToSqlQuery(...)

Params

  • totalCount - count of line for whole SQL SELECT
  • paginationArgs - provided from connectionArgs fn from graphql-relay-js
  • callbackWithValues - callback return object with offset and limit computed values

return

  • Connection with sql results & totalCount

Example

Raw function API example

// graphql resolver
// ...
return connectionToSqlQuery(
  // this return totalCount for current select
  await someOrmSqlModel.getTotalCount(), 
  paginationArgs,
  // get computed values for sql pagination
  ({ offset, limit }) => (
    // applying it to sql select for native sql pagination
    someOrmSqlModel.getData({ offset, limit })
  )
)

Example with graphQl resolver for users

import { connectionToSqlQuery } from 'graphql-cursor-sql-helper'
/*
    _          _                              _          _  
  >(')____,  >(')____,   ... some code ...  >(')____,  >(') ___, 
    (` =~~/    (` =~~/   ... some code ...   (` =~~/    (` =~~/ 
~^~~^~^`---'~^~^~^`---'~^~^~^`---'~^~^~^`---'~^~^~^`---'~^~^~ 
*/
const Admin = new GraphQLObjectType({
  name: 'Admin',
  description: '...',
  interfaces: [nodeInterface],
  isTypeOf: obj => instanceof sqlModelAdmin,
  fields: () => ({
    /*
       _          _                              _          _  
     >(')____,  >(')____,   ... some code ...  >(')____,  >(') ___, 
       (` =~~/    (` =~~/   ... some code ...   (` =~~/    (` =~~/ 
    ~^~~^~^`---'~^~^~^`---'~^~^~^`---'~^~^~^`---'~^~^~^`---'~^~^~ 
    */
    users: {
      type: connectionDefinitions({
        name: 'User',
        nodeType: UserType,
        // adding connectionFields to type
        // is necessary for quering totalCount in graphQl
        connectionFields: {
          totalCount: { type: new GraphQLNonNull(GraphQLInt) }
        }
      }).connectionType,
      args: connectionArgs,
      description: `...`,
      resolve: async (parent, paginationArgs) => {
        // call `graphql-sql-cursor-helper` function for calculating real OFFSET & LIMIT
        return connectionToSqlQuery(
          await someOrmSqlModel.getTotalCount(), // <- this 
          paginationArgs,
          // get computed values for sql pagination
          ({ offset, limit }) => (
            // applying it to sql select for native sql pagination
            someOrmSqlModel.getUsers({ offset, limit })
          )
        )
      }
    }
  })
})

## Contributing

After cloning this repo, ensure dependencies are installed by running:

npm install or yarn

Develop by

yarn run start or npm run start

Test changes by

yarn run test or npm run test