graphql-fields

Turns a GraphQL resolver's info argument into a flat map of every requested field, honoring @include/@skip directives.

Library
npm
v2.0.3
347stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
33/100Needs Attention
Development Activity0
Maintenance0
Community52
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
45/100Fair
Architecture58
Code Quality55
Innovation40
Learning Curve25

graphql-fields solves a narrow but common problem in GraphQL servers that proxy to REST or other field-selective backends: knowing exactly which fields a client asked for, at any nesting depth, without walking the query AST by hand. Given the info object passed to any resolver, it flattens all fragments (both inline and named spreads) and merges duplicate field selections into a single nested object, so a resolver can inspect graphqlFields(info) and see a plain JS object mirroring the requested selection set.

It correctly respects @include and @skip directives, excluding fields whose condition evaluates to false, and can optionally attach parsed __arguments to each field or exclude specific field names (like __typename) from the output. The typical use case is building a REST query string or database projection from only the fields a GraphQL client actually asked for, avoiding over-fetching from an underlying API.

What You Get

  • A single graphqlFields(info, obj, opts) function that returns a flat, nested object of requested field names
  • Automatic flattening of inline fragments and named fragment spreads into the parent selection
  • Correct handling of @include(if:) and @skip(if:) directives, including variable-backed conditions
  • Optional processArguments mode that attaches a __arguments array (with kind/value) to any field with arguments
  • An excludedFields option to drop noise fields like __typename from the resulting map
  • Zero runtime dependencies — a single 129-line module with no external packages required at runtime

Common Use Cases

  • Translating a GraphQL query’s field selection into a REST API query string (e.g. ?fields=profile,id) so the underlying service returns only the requested data
  • Building a database projection (e.g. a Mongo .select() or SQL column list) that matches exactly what the client’s query asked for, avoiding over-fetching
  • Detecting at resolve time whether an expensive nested field (like a joined relation) was actually requested before doing the work to compute it
  • Passing a normalized field-selection object down to a downstream microservice call so it can trim its own response payload

Under The Hood

Architecture graphql-fields is a single 129-line CommonJS module (index.js) exporting one function, graphqlFields(info, obj, opts). Internally it recurses through flattenAST, which walks each AST node’s selectionSet.selections (via the getSelections helper), resolves named fragment spreads back to their definitions using info.fragments (via getAST/isFragment), and merges the results into a shared accumulator object. Directive handling (getDirectiveResults, getDirectiveValue) and argument parsing (getArguments, getArgumentValue) are implemented as separate pure-ish helper functions layered on top of the same traversal. The one architectural wrinkle is a module-level mutable options object used to thread processArguments/excludedFields through the recursive calls instead of passing them as parameters — functional but not reentrant-safe if the module were ever called concurrently with different options in the same tick, which is a real (if narrow) risk in a single shared Node process.

Tech Stack The package has zero runtime dependencies — it consumes only the GraphQLResolveInfo shape from graphql-js without importing the graphql package itself. Development tooling is Babel-based: @babel/core, @babel/preset-env, and @babel/cli compile index.js to build/index.js (the published main entry) targeting “last 2 versions” of browsers plus the current Node. Tests run via Mocha with Node’s built-in assert, and graphql (^15.0.0) is a dev-only dependency used to construct real schemas in tests. CI is a .travis.yml matrix across Node 10/12/14 — dated infrastructure reflecting the project’s 2016-2023 active window.

Code Quality A single 690-line test file (test/index_spec.js) exercises fragment flattening, duplicate-field merging, and directive/argument handling against realistic nested GraphQLObjectType schemas — coverage is thorough for the library’s narrow surface area, using Mocha’s describe/it structure and plain assert calls rather than a heavier assertion library. There is no TypeScript and no type definitions shipped, no ESLint or Prettier configuration in the repo, and no static analysis beyond what Babel’s transpile step catches. Error handling is minimal — the code assumes well-formed GraphQL AST input and does not defensively guard against malformed info objects.

What Makes It Unique The library targets one specific, recurring pain point — knowing which fields a GraphQL query selected so a REST-backed or field-selective resolver can avoid over-fetching — and solves it with a small, self-contained AST walk rather than a general-purpose GraphQL execution or introspection layer. Its own README is unusually candid about its limits: it carries a deprecation notice pointing at graphql-parse-resolve-info for use cases this library doesn’t cover, particularly around fragment edge cases and interface/union types. That honesty, combined with its zero-dependency footprint, made it a popular lightweight choice for years, but the maintainer’s own guidance is that a more complete alternative should be preferred for anything beyond straightforward field-flattening today.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search