npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

gql-paginator

v2.2.0

Published

This repository offers utilities and tools to streamline efficient pagination of GraphQL queries in applications using the GitHub API. It simplifies the management of paginated results and provides a ready-to-use solution for your GraphQL-based projects i

Downloads

36

Readme

gql-paginator

This repository offers utilities and tools to streamline efficient pagination of GraphQL queries in applications using the GitHub API. It simplifies the management of paginated results and provides a ready-to-use solution for your GraphQL-based projects interacting with API data.


Installation

  1. Open the repository where you want to install the library
  2. Run this command in a command console:
npm install gql-paginator
  1. Import the library in the js file in which you want to use the functions:
const { GQLPaginator } = require('gql-paginator');

Usage

GQLPaginator function

This async function receives a query, a token, and a configuration, and returns the paginated result if possible or the non-paged result if not. Result's examples

result = await GQLPaginator(query, token, configuration);

Parameters:

  • Query: Add the query you need to paginate, and put it in quotes. Remember that to paginate you need to build a query that provides the information necessary to do so. How to build a valid query for pagination?
  • Token: Your API token in quotes. You can find more information on how to generate a token on the page of the API you are using.
  • Configuration: The required pagination configuration of the API in use. You can also create your own configuration or modify existing ones by following the configuration creation and editing guide. Default configurations:
    • github-v1.0.0
    • zenhub-v1.0.0

Query and Configuration

How to build a valid query for pagination?

In order for pagination to be carried out, it is necessary to follow a series of rules when building the query (example), which are listed below:

  • All pageable types must contains:
  nodes {
    id
  }
  pageInfo {
    hasNextPage
    endCursor
  }  
  totalCount
  • Query mustn't contains:
    • after

Configuration creation and extend guide

The configuration chosen when calling the GQLPaginator function defines certain parameters that are necessary to know in order to paginate a result. This is due to the variability of GraphQL when generating subqueries. This section explains how to modify existing configurations or create a new one for an unsupported API.

Creating a configuration

(This requires studying how the GraphQL API you are using works)

  1. Go to your repository from opening the path node_modules/gql-paginator/configurations/sources
  2. Create a new configuration called: "api-name"-v1.0.0.json
  3. Use this template to create a new API configuration
{
    "id": "",
    "url": "",
    "complexSubqueryPath": , 
    "firstLevelPtype": [],
    "paths":{
    }
}
  1. Fill out all the fields following the explanation below (It's recommended to compare what you fill in with the default configurations):
    • id: "api-name"-v1.0.0
    • url: api url.
    • complexSubqueryPath: if the subquery of your api is made following the github (PullRequestReview) structure then true, if they are made like zenhub (only Review) then false.
    • firstLevelPtype: if complexSubqueryPath is true then fill the array with only first level types.
    • paths: the paths of your query with the necessary value to generate a correct subquery.

Extending a configuration

If you are using an existing configuration and you call the function with the correct parameters, but the configuration does not include the pageable object that you want to page, it will let you know through the logs in the console and describe the paths that you should add.

Example:

I have this github-v1.0.0 configuration:

{
    "id": "github-v1.0.0",
    "url": "https://api.github.com/graphql",
    "complexSubqueryPath": true, 
    "firstLevelPtype": ["pullRequests","issues"],
    "paths":{
        "pullRequests.*": "PullRequest",
        "issues.*": "Issue"
    }
}

When I try to paginate my github query that you can find in the examples, the console will return this error:

2023-10-30 13_13_11-github-v1 0 0 json - github-gql-paginator - Visual Studio Code

Solution: add the path in the specified json

{
    "id": "github-v1.0.0",
    "url": "https://api.github.com/graphql",
    "complexSubqueryPath": true, 
    "firstLevelPtype": ["pullRequests","issues"],
    "paths":{
        "pullRequests.*": "PullRequest",
        "issues.*": "Issue",
        "pullRequests.reviews.*": "PullRequestReview"
    }
}

Examples

github-v1.0.0

Change ${repository-name} and ${user-name} to the repository name that you are using and your user name. Change ${token} to your github token.

GQLPaginator(`{
  repository(name: "${repository-name}", owner:"${user-name}") {
    issues(first: 1) {
      totalCount
      pageInfo {
        hasNextPage
        endCursor
      }
      nodes {
        id
        title
      }
    }
    pullRequests(first: 1) {
      totalCount
      pageInfo {
        endCursor
      }
      nodes {
        id
        state
        title
        body
        baseRefName
        headRefName
        createdAt
        author {
          login
        }
        mergedAt
        mergedBy {
          login
        }
        reviews(first: 1) {
          totalCount
          pageInfo {
            hasNextPage
            endCursor
          }
          nodes {
            id
            createdAt
            state
            reactions (first: 1) {
              totalCount
              pageInfo {
                hasNextPage
                endCursor 
              }
              nodes {
                content
                id
                user{
                  name
                }
              }
            }
          }
        }
        assignees(first: 1){
          pageInfo {
            hasNextPage
            endCursor
          }
          totalCount
          nodes{
            id
            name
          }
        }
      }
    }
  }
}`, ${token}, 'github-v1.0.0')

If you look at the query, pullRequests (paginable type) does not have the hasNextPage attribute within pageInfo, which was a mandatory requirement to be able to paginate. Therefore, pullRequests will not be paged, but the rest of the pageable types will be. You can add hasNextPage attribute and you'll see how now the pagination is done in pullRequests.

Obtained result:

{
  "data": {
    "repository": {
      "issues": {
        "totalCount": 52,
        "pageInfo": {
          "hasNextPage": true,
          "endCursor": "Y3Vyc29yOnYyOpHOYHBmyA=="
        },
        "nodes": [
          {
            "id": "I_kwDOI8VKA85e5OIH",
            "title": "Task #2.6 Technical report and task diagram"
          },
          {
            "id": "I_kwDOI8VKA85e5O3A",
            "title": "Task #2.7 Methodologies management report"
          },
          {
            "id": "I_kwDOI8VKA85e5QOJ",
            "title": "Task #2.8 a) Pet hotel functionality"
          },
          {
            "id": "I_kwDOI8VKA85e5Qt7",
            "title": "Task #2.8 b) Web style"
          },
          {
            "id": "I_kwDOI8VKA85e5RDZ",
            "title": "Task #2.8 c) Add and edit veterinarians"
          },
          ...

zenhub-v1.0.0

Change ${repository-id} to the repository name that you can find it in your board url:

Captura de pantalla 2023-10-31 093835

Change ${token} to your zenhub token.

GQLPaginator(`query {
  workspace(id: "${repository-id}") {
    repositoriesConnection(first: 10) {
      nodes {
        id
        ghId
        name
        issues(first:5){
           pageInfo{
            hasNextPage
            endCursor
           }
           totalCount
           nodes{
            id
            title
            timelineItems(first:10){
              pageInfo{
                hasNextPage
                endCursor
              }
              totalCount
              nodes{
                id
                data
                key
                updatedAt
              }
            }
          }
        }
        owner {
          login
        }
      }
    }
  }
}`, ${token}, 'zenhub-v1.0.0')

Obtained result:

{
  "data": {
    "workspace": {
      "repositoriesConnection": {
        "nodes": [
          {
            "id": "Z2lkOi8vcmFwdG9yL1JlcG9zaXRvcnkvMTMzMzk2MDE4",
            "ghId": 600132099,
            "name": "psg2-2223-g6-63",
            "issues": {
              "pageInfo": {
                "hasNextPage": true,
                "endCursor": "WzI2MjAyMDU4NV0"
              },
              "totalCount": 76,
              "nodes": [
                {
                  "id": "Z2lkOi8vcmFwdG9yL0lzc3VlLzI2MDg0ODA4NA",
                  "title": "Task #2.9 Deployment",
                  "timelineItems": {
                    "pageInfo": {
                      "hasNextPage": false,
                      "endCursor": "MQ"
                    },
                    "totalCount": 1,
                    "nodes": [
                      {
                        "id": "Z2lkOi8vcmFwdG9yL1RpbWVsaW5lSXRlbTo6SXNzdWVFc3RpbWF0ZUNoYW5nZWQvMTExNTc0MDA3",
                        "data": {
                          "github_user": {
                            "id": 313464417,
                            "gh_id": 100673872,
                            "login": "JaviFdez7",
                            "avatar_url": "https://avatars.githubusercontent.com/u/100673872?v=4"
                          },
                          "current_value": "2.0"
                        },
                        "key": "issue.set_estimate",
                        "updatedAt": "2023-03-20T01:17:30Z"
                      }
                    ]
                  }
                },
                {
                  "id": "Z2lkOi8vcmFwdG9yL0lzc3VlLzI2MDg0ODA4Ng",
                  "title": "Task #2.6 Technical report and task diagram",
                  "timelineItems": {
                    "pageInfo": {
                      "hasNextPage": false,
                      "endCursor": "MQ"
                    },
                    "totalCount": 1,
                    "nodes": [
                      {
                        "id": "Z2lkOi8vcmFwdG9yL1RpbWVsaW5lSXRlbTo6SXNzdWVFc3RpbWF0ZUNoYW5nZWQvMTExMzk1NDM0",
                        "data": {
                          "github_user": {
                            "id": 313464417,
                            "gh_id": 100673872,
                            "login": "JaviFdez7",
                            "avatar_url": "https://avatars.githubusercontent.com/u/100673872?v=4"
                          },
                          "current_value": "8.0"
                        },
                        "key": "issue.set_estimate",
                        "updatedAt": "2023-03-15T15:41:06Z"
                      }
                    ]
                  }
                },
                ...

Design and architecture

The GQLPaginator function is a recursive function that follows the following flow:

gql-paginator-arquitecture (1)

Assumptions:

  • Arrays only exist in nodes, an array is not contemplated elsewhere.
  • When an object has nodes as a property, it is considered a pageable type.
  • Pageable types are not contemplated in a simple type.