Functions for modifying GraphQL documents including removing directives, adding __typename fields, and transforming document structure.
Removes specified directives from a GraphQL document, with optional field removal when directives match.
/**
* Remove directives from a GraphQL document
* @param directives - Array of directive removal configurations
* @param doc - GraphQL document to transform
* @returns Modified document with directives removed, or null if document becomes empty
*/
function removeDirectivesFromDocument(
directives: RemoveDirectiveConfig[],
doc: DocumentNode
): DocumentNode | null;Usage Example:
import { removeDirectivesFromDocument } from "apollo-utilities";
import { parse } from "graphql";
const query = parse(`
query GetUser {
user @client {
name
email @deprecated(reason: "Use contact.email")
profile @connection(key: "profile") {
bio
}
}
}
`);
// Remove all @client directives and their fields
const config = [
{
name: "client",
remove: true // Also remove the field containing this directive
}
];
const cleanedQuery = removeDirectivesFromDocument(config, query);
console.log(print(cleanedQuery));
// query GetUser {
// // user field completely removed because it had @client
// }
// Remove just the directive but keep the field
const config2 = [
{
name: "deprecated",
remove: false // Only remove directive, keep field
}
];
const result = removeDirectivesFromDocument(config2, query);
// email field remains but @deprecated directive is removedAdds __typename fields to all selection sets in a GraphQL document for caching purposes.
/**
* Add __typename fields to all selection sets in a document
* @param doc - GraphQL document to transform
* @returns Document with __typename fields added
*/
function addTypenameToDocument(doc: DocumentNode): DocumentNode;Usage Example:
import { addTypenameToDocument } from "apollo-utilities";
import { parse } from "graphql";
const query = parse(`
query GetUser {
user {
name
posts {
title
comments {
text
}
}
}
}
`);
const queryWithTypename = addTypenameToDocument(query);
console.log(print(queryWithTypename));
// query GetUser {
// user {
// name
// posts {
// title
// comments {
// text
// __typename
// }
// __typename
// }
// __typename
// }
// }Special Handling:
Removes @connection directives from a GraphQL document, with warnings for missing key parameters.
/**
* Remove @connection directives from document
* @param doc - GraphQL document to transform
* @returns Document with @connection directives removed
*/
function removeConnectionDirectiveFromDocument(doc: DocumentNode): DocumentNode | null;Usage Example:
import { removeConnectionDirectiveFromDocument } from "apollo-utilities";
import { parse } from "graphql";
const query = parse(`
query GetUser {
user {
posts @connection(key: "userPosts") {
edges {
node {
title
}
}
}
}
}
`);
const cleanedQuery = removeConnectionDirectiveFromDocument(query);
// @connection directive is removed but posts field remainsExtracts only the parts of a document that contain specified directives.
/**
* Extract parts of document that contain specified directives
* @param directives - Array of directive configurations to match
* @param doc - GraphQL document to analyze
* @returns Document containing only selections with matching directives
*/
function getDirectivesFromDocument(
directives: GetDirectiveConfig[],
doc: DocumentNode
): DocumentNode;Usage Example:
import { getDirectivesFromDocument } from "apollo-utilities";
import { parse } from "graphql";
const query = parse(`
query GetUser {
user {
name
email @client
posts {
title @client
content
}
}
}
`);
const clientConfig = [{ name: "client" }];
const clientOnlyDoc = getDirectivesFromDocument(clientConfig, query);
console.log(print(clientOnlyDoc));
// query GetUser {
// user {
// email @client
// posts {
// title @client
// }
// }
// }
// Only fields with @client directive are preservedRemoves specified arguments from fields and operation variable definitions.
/**
* Remove arguments from document fields and operation variables
* @param config - Array of argument removal configurations
* @param doc - GraphQL document to transform
* @returns Document with specified arguments removed
*/
function removeArgumentsFromDocument(
config: RemoveArgumentsConfig[],
doc: DocumentNode
): DocumentNode;Usage Example:
import { removeArgumentsFromDocument } from "apollo-utilities";
import { parse } from "graphql";
const query = parse(`
query GetUsers($status: String, $limit: Int) {
users(status: $status, limit: $limit) {
name
}
}
`);
const config = [
{ name: "status" } // Remove all arguments that use $status variable
];
const result = removeArgumentsFromDocument(config, query);
// $status variable definition and status argument are removed
// $limit remains unchangedRemoves specified fragment spreads and their definitions from a document.
/**
* Remove fragment spreads and definitions from document
* @param config - Array of fragment spread removal configurations
* @param doc - GraphQL document to transform
* @returns Document with specified fragments removed
*/
function removeFragmentSpreadFromDocument(
config: RemoveFragmentSpreadConfig[],
doc: DocumentNode
): DocumentNode;Converts any operation into a query operation while preserving the selection set.
/**
* Convert operation to query operation
* @param document - GraphQL document to transform
* @returns Document with operation converted to query type
*/
function buildQueryFromSelectionSet(document: DocumentNode): DocumentNode;Usage Example:
import { buildQueryFromSelectionSet } from "apollo-utilities";
import { parse } from "graphql";
const mutation = parse(`
mutation CreateUser($input: UserInput!) {
createUser(input: $input) {
id
name
email
}
}
`);
const queryVersion = buildQueryFromSelectionSet(mutation);
console.log(print(queryVersion));
// query CreateUser($input: UserInput!) {
// createUser(input: $input) {
// id
// name
// email
// }
// }
// Operation type changed from mutation to queryRemoves fields and selection sets that contain @client directives, used for separating server and client-only operations.
/**
* Remove @client directive fields from document
* @param document - GraphQL document to transform
* @returns Document with @client fields removed, or null if document becomes empty
*/
function removeClientSetsFromDocument(document: DocumentNode): DocumentNode | null;Usage Example:
import { removeClientSetsFromDocument } from "apollo-utilities";
import { parse } from "graphql";
const query = parse(`
query GetUser {
user {
id
name
email
isLoggedIn @client
localPreferences @client {
theme
notifications
}
}
}
`);
const serverOnlyQuery = removeClientSetsFromDocument(query);
console.log(print(serverOnlyQuery));
// query GetUser {
// user {
// id
// name
// email
// }
// }
// @client fields are completely removedinterface RemoveNodeConfig<N> {
/** Name of the node to match */
name?: string;
/** Custom test function for matching nodes */
test?: (node: N) => boolean;
/** Whether to remove the entire field/node when directive matches */
remove?: boolean;
}
interface GetNodeConfig<N> {
/** Name of the node to match */
name?: string;
/** Custom test function for matching nodes */
test?: (node: N) => boolean;
}
type RemoveDirectiveConfig = RemoveNodeConfig<DirectiveNode>;
type GetDirectiveConfig = GetNodeConfig<DirectiveNode>;
type RemoveArgumentsConfig = RemoveNodeConfig<ArgumentNode>;
type GetFragmentSpreadConfig = GetNodeConfig<FragmentSpreadNode>;
type RemoveFragmentSpreadConfig = RemoveNodeConfig<FragmentSpreadNode>;
type RemoveFragmentDefinitionConfig = RemoveNodeConfig<FragmentDefinitionNode>;
type RemoveVariableDefinitionConfig = RemoveNodeConfig<VariableDefinitionNode>;// Remove directives based on custom logic
const config = [
{
test: (directive: DirectiveNode) => {
return directive.name.value === "deprecated" &&
directive.arguments?.some(arg =>
arg.name.value === "reason" &&
arg.value.kind === "StringValue" &&
arg.value.value.includes("legacy")
);
},
remove: true
}
];
const result = removeDirectivesFromDocument(config, document);import {
removeClientSetsFromDocument,
addTypenameToDocument,
removeConnectionDirectiveFromDocument
} from "apollo-utilities";
// Chain multiple transformations
let transformedDoc = removeClientSetsFromDocument(originalDoc);
if (transformedDoc) {
transformedDoc = removeConnectionDirectiveFromDocument(transformedDoc);
if (transformedDoc) {
transformedDoc = addTypenameToDocument(transformedDoc);
}
}