New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

graphql-fields-list

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-fields-list

Extracts and returns list of fields requested from graphql resolver info object

  • 1.1.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
20K
increased by3.2%
Maintainers
1
Weekly downloads
 
Created
Source

graphql-fields-list

Build Status codebeat badge Coverage Status David Known Vulnerabilities License

Add-on to work with GraphQLResolveInfo which helps to extract requested fields list for a particular object resolver. This helps to bypass requested fields data to underlying services or data sources to extract only those minimal parts of data which was requested by end-user.

TypeScript Included!!!

Install

npm i graphql-fields-list

With JavaScript:

const { fieldsList, fieldsMap } = require('graphql-fields-list');

With TypeScript:

import { fieldsList, fieldsMap } from 'graphql-fields-list';

Motivation and Usage

Let's assume we have the following GraphQL schema:

interface Node {
  id: ID!
}
type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}
type Query {
  node(id: ID!): Node
  viewer: Viewer
}
type User implements Node {
  id: ID!
  firstName: String
  lastName: String
  phoneNumber: String
  email: String
}
type UserConnection {
  pageInfo: PageInfo!
  edges: [UserEdge]
}
type UserEdge {
  node: User
  cursor: String!
}
type Viewer {
  users(
    after: String,
    first: Int,
    before: String,
    last: Int
  ): UserConnection
}

And using the query:

query UserNames query {
    viewer {
        users {
            pageInfo {
                startCursor
                endCursor
            }
            edges {
                cursor
                node {
                    id
                    firstName
                    lastName
                }
            }
        }
    }
}

Our goal is to extract and return ONLY id, firstName and lastName fields from the user data. To achieve that we would need to bypass required fields information to underlying service or database, for example, let's assume we want to select that kind of data from mongodb.

In this case we will need to implement a resolver which will fetch only requested fields from our database like this:

const { connectionFromArray } from 'graphql-relay';
const { fieldsList } = require('graphql-fields-list');
// ... assuming we implement resolver on 'viewer' node:
async resolve(src, args, context, info) {
    // we want to get a clue which user data fields are requested, so:
    const fields = fieldsList(info, { path: 'users.edges.node' });
    // RESULT: fields = ['id', 'firstName', 'lastName']
    // Now we can fetch from mongodb only required part of the data
    // instead of fetching entire user data document (assuming
    // userDb is initialized model of mongoose):
    const users = await userDb.find().select(fields.join(' ')).exec();
    return { viewer: { users: connectionFromArray(users, args) } };
}

In the example above we assume our user model in database contains the same field names as defined by a graphql request. BTW, in a real world, there could be a need to re-map field names from a graphql query to some different names stored in a database. For example, we would need to use automatically created _id field in mongodb as id field in a graphql request. This can be easily achieved specifying a transform map option:

const fields = fieldsList(info, {
    path: 'users.edges.node',
    transform: { id: '_id' },
});
// RESULT: fields = ['_id', 'firstName', 'lastName']

By the way, in some particular cases there could be a need to retrieve a whole fields name hierarchy from a graphql request. This could be achieved using fieldsMap function:

const { fieldsMap } = require('graphql-fields-list');
// ... inside the resolver as we did above:
const map = fieldsMap(info);
/*
RESULT:
map = {
  users: {
    pageInfo: {
      startCursor: false,
      endCursor: false
    },
    edges: {
      cursor: false,
      node: {
        id: false,
        firstName: false,
        lastName: false
      }
    }
  }
}
*/

Function fieldsMap also accepts path optional argument, which allows to retrieve only a required part of the map:

const map = fieldsMap(info, 'users.pageInfo');
/*
RESULT:
map = {
  startCursor: false,
  endCursor: false
}
*/

For leafs of the fields tree it will return false value, which is usable when you need to detect that the end of a tree branch is reached during traversal.

Both fieldsMap and fieldsList work as expected with graphql query fragmentation, so can be safely used within any possible queries.

Since version 1.1.0 it also supports @skip and @include directives in queries. This is enabled by default. If you need to disable directives support for some reason it may be turned off using withDirectives = false option correspondingly:

fieldsList(info, { withDirectives: false })
fieldsMap(info, null, false);

License

ISC Licence

Keywords

FAQs

Package last updated on 23 Oct 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc