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 🙏

© 2026 – Pkg Stats / Ryan Hefner

graphql-fragment-normalizer

v0.3.1

Published

Schema-aware GraphQL fragment expansion and normalization for ASTs and GraphQL Code Generator.

Readme

NPM Version NPM Downloads Build Status

graphql-fragment-normalizer

Normalizes GraphQL documents by expanding fragment spreads and inline fragments with schema-aware type checks.

This package can be used directly with GraphQL ASTs, or as a GraphQL Code Generator plugin that rewrites documents before later plugins generate their output.

You can try the library here: graphql-fragment-normalizer REPL

Motivation

GraphQL fragments are useful for colocating field selections, but some consumers work better with operations whose fragments have already been expanded. For example, generated document strings may need to be self-contained, or downstream tooling may need to inspect the final field selection without resolving fragment references itself.

graphql-fragment-normalizer expands fragments while using the schema to keep only selections that are valid for the current type. It can flatten compatible fragments, preserve type-narrowing selections as inline fragments, merge repeated field selections, and optionally keep named fragments when they should remain available for generated fragment types.

Packages such as @graphql-tools/relay-operation-optimizer already provide operation normalization, but they are designed for Relay-style optimization and can apply broader, more complex rewrites. This package focuses on a smaller transformation surface: expanding and normalizing fragments while keeping the resulting document close to the original operation shape.

Usage

Installing

npm install graphql-fragment-normalizer graphql

Using the API

import { buildSchema, parse, print } from 'graphql';
import { expandFragments } from 'graphql-fragment-normalizer';

const schema = buildSchema(`
  type Query {
    user: User
  }

  type User {
    id: ID!
    name: String!
  }
`);

const document = parse(`
  query GetUser {
    user {
      ...UserFields
    }
  }

  fragment UserFields on User {
    id
    name
  }
`);

const normalizedDocument = expandFragments(schema, document);

console.log(print(normalizedDocument));

Output:

query GetUser {
  user {
    id
    name
  }
}

By default, fragment definitions are removed from the returned document after the operations have been expanded.

Using with GraphQL Code Generator

Add the plugin graphql-fragment-normalizer/codegen-plugin before the plugin or preset that should receive normalized documents:

import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'schema.graphql',
  documents: ['src/**/*.graphql'],
  generates: {
    'src/generated/': {
      preset: 'client',
      plugins: [
        {
          'graphql-fragment-normalizer/codegen-plugin': {
            preserveNarrowingFragments: true,
          },
        },
      ],
    },
  },
};

export default config;

The Code Generator plugin mutates the loaded documents in place and returns no generated content by itself. It also collects fragments from all input document files, so operations can be normalized even when fragments are split into separate files.

For Code Generator usage, fragment definitions are preserved so that later plugins can still generate colocated fragment types.

The plugin is exported through the graphql-fragment-normalizer/codegen-plugin subpath. If you need to import the plugin function directly, use that subpath instead of the main package entry.

The options (configurations) for the plugin can be ExpandFragmentsOptions as described below.

Options

export interface ExpandFragmentsOptions {
  readonly additionalFragments?: readonly FragmentDefinitionNode[];
  readonly operationName?: string | null | undefined;
  readonly preserveNarrowingFragments?: boolean;
  readonly distributeAbstractFragments?: boolean;
  readonly preserveNamedFragmentsUsedAtLeast?: number;
  readonly fragmentDefinitionsMode?: 'drop' | 'normalize' | 'preserve';
  readonly missingFragmentBehavior?: 'error' | 'warn' | 'ignore';
  readonly typeRelationContext?: TypeRelationContext;
}
  • additionalFragments: Fragment definitions supplied outside the document being expanded.
  • operationName: Expands only the named operation. When omitted, all operations are expanded.
  • preserveNarrowingFragments: Keeps fragments that narrow from the current type to a more specific type as inline fragments. Defaults to true.
  • distributeAbstractFragments: Emits abstract narrowing fragments as inline fragments for each reachable concrete object type. Defaults to false.
  • preserveNamedFragmentsUsedAtLeast: Keeps named fragment spreads when a fragment is used at least this many times. Values less than or equal to 0 disable this behavior.
  • fragmentDefinitionsMode: Controls input FragmentDefinition nodes in the returned document. drop removes them after expansion, preserve keeps them unchanged, and normalize keeps and normalizes them. Defaults to drop.
  • missingFragmentBehavior: Controls unresolved named fragment spreads. error throws, warn logs a warning and omits the spread, and ignore omits it silently. Defaults to error.
  • typeRelationContext: Reusable type-relation cache created with createTypeRelationContext(schema).

The Code Generator plugin accepts the same options except additionalFragments, fragmentDefinitionsMode, and typeRelationContext, which are managed internally. (The plugin always sets fragmentDefinitionsMode to preserve to keep fragment definitions for following generating processes.)

APIs

import {
  createTypeRelationContext,
  expandFragments,
  expandFragmentsInFragment,
  type ExpandFragmentsOptions,
  type FragmentDefinitionsMode,
  type TypeRelationContext,
} from 'graphql-fragment-normalizer';

expandFragments(schema, document, options?)

Expands fragment spreads and inline fragments inside a DocumentNode using schema type information.

const normalizedDocument = expandFragments(schema, document, {
  fragmentDefinitionsMode: 'normalize',
  preserveNamedFragmentsUsedAtLeast: 2,
});

expandFragmentsInFragment(schema, fragment, options?)

Expands fragment spreads and inline fragments inside a single FragmentDefinitionNode.

const normalizedFragment = expandFragmentsInFragment(schema, fragment, {
  additionalFragments,
});

createTypeRelationContext(schema)

Creates a reusable cache for schema type relation checks. Reuse it when expanding multiple documents against the same schema.

const typeRelationContext = createTypeRelationContext(schema);

const first = expandFragments(schema, firstDocument, { typeRelationContext });
const second = expandFragments(schema, secondDocument, { typeRelationContext });

Development Note

Parts of this package were developed with assistance from AI tools. The published code is reviewed, tested, and maintained by the package author.

License

MIT License