graphql-list-fields
Extracts the list of fields a client requested from a GraphQL resolver's info object, fragments and directives included.
Repository Health
Technical Analysis
graphql-list-fields solves a narrow but common problem in GraphQL server development: knowing exactly which fields a client asked for inside a resolver, so you only fetch or compute what’s needed instead of everything a type could expose. Given the GraphQLResolveInfo object every resolver already receives, it walks the query’s AST and returns a flat array of field names in dot notation for nested selections.
The implementation resolves fragments (both named fragment ... on Type and inline ... on Type) and honors @skip/@include directives, so the returned field list matches what will actually be included in the response rather than what’s merely present in the query text. An optional maxDepth argument caps how many levels of nesting are traversed, which is useful when you only need top-level field names for something like a database projection or an external API’s sparse fieldset parameter.
It has no runtime dependencies and is a single ~70-line file, making it easy to audit and drop into any graphql-js-based server (Apollo Server, express-graphql, Yoga, etc.) without pulling in additional weight.
What You Get
- A
getFieldNames(info, maxDepth?)function that returns a plain array of requested field names - Automatic resolution of named fragments (
fragment X on Type { ... }) into the flat field list - Automatic resolution of inline fragments (
... on Type { ... }) - Correct handling of
@skipand@includedirectives, including variable-based conditions - Dot-notation paths for nested selections (e.g.
address.city) - Optional depth limiting via the second argument to restrict how deep nested fields are reported
Common Use Cases
- Passing only the requested fields to a downstream REST API’s sparse-fieldset query parameter
- Building a MongoDB/SQL projection so a resolver only selects the columns or fields actually queried
- Deciding whether an expensive nested field was requested before computing it
- Logging or metrics on which GraphQL fields are queried most often in production
Under The Hood
Architecture
The entire package is a single file, index.js, exporting one function, getFieldList, which delegates to an internal getFieldSet that recursively walks the GraphQL AST reachable from info.fieldASTs/info.fieldNodes. Each AST node’s kind (Field, InlineFragment, FragmentSpread) is switched on to decide whether to record a dot-notation field path, recurse into an inline fragment’s selection set, or look up a named fragment from info.fragments and recurse into that; a small helper (isExcludedByDirective) evaluates @skip/@include directives against info.variableValues before a node is included, and the recursion stops early once maxDepth is exhausted. Because there’s a single entry point and no internal state, the whole module is one dependency-free tree walk with an accumulator object as its only data structure — nothing else in a consuming application can break by depending on it beyond the shape of the returned array.
Tech Stack
The package itself has zero runtime dependencies; it operates purely on the AST shapes defined by the graphql (graphql-js) reference implementation, which is listed only as a devDependency for the test suite. Tests run under Jest with coverage collection, and formatting is standardized through Prettier with an explicit tab-width/quote-style configuration. There is no build step — index.js is published as-is, and CI (GitHub Actions, .github/workflows/node.js.yml) runs npm ci && npm test on Node 24 against pushes and PRs to master.
Code Quality
The test suite in __tests__/test.js builds a small real GraphQLSchema with nested object types and runs actual graphql() executions against it, asserting on the field list captured inside a resolver spy — this exercises the library through its real integration surface rather than mocking the AST, and covers basic fields, fragments, inline fragments, directive-based skipping, and depth limiting. There are no TypeScript types or type declarations, and error handling is minimal (a malformed AST node kind is silently ignored via the switch falling through), which is a reasonable tradeoff for a small, stable utility but means misuse gives no explicit feedback. Naming is plain and consistent throughout the small file, and there’s no linter configured beyond Prettier.
API Design
The library exposes exactly one export — a default function — matching the common require('graphql-list-fields') pattern shown directly in the README, which lowers the integration cost to a single import and a one-line call inside any resolver. The optional maxDepth parameter has a sensible default (Number.MAX_SAFE_INTEGER, i.e. unlimited) so the common case needs no configuration at all, and dot-notation output composes naturally with projection-building code without requiring the caller to walk a tree themselves.
Used by 2 apps in this directory
Parse Server
Developer Tools · Databases
Self-hosted Backend-as-a-Service for Node.js with REST, GraphQL, real-time Live Query, cloud code, and pluggable adapters for any infrastructure.
Wiki.js
Knowledge Management · Collaboration
A modern, self-hosted wiki platform built on Node.js with a rich plugin ecosystem for authentication, search, storage, and rendering that adapts to any team's infrastructure.