or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

ast-operations.mddirectives.mdexecution-resolution.mdfield-type-operations.mdindex.mdschema-transformation.mdutilities.md
tile.json

field-type-operations.mddocs/

Field & Type Operations

Field collection, iteration, and type manipulation utilities for analyzing GraphQL schemas and execution contexts. These tools are essential for field resolution, schema analysis, and type relationship management.

Capabilities

Field Collection

Collect and organize fields from GraphQL selection sets during execution.

/**
 * Collect fields from a selection set, handling fragments and inline fragments
 * @param schema - The GraphQL schema
 * @param fragments - Map of fragment definitions
 * @param variableValues - Variable values for the request
 * @param runtimeType - The runtime object type
 * @param selectionSet - The selection set to collect from
 * @returns Collected fields and patches
 */
function collectFields(
  schema: GraphQLSchema,
  fragments: Record<string, FragmentDefinitionNode>,
  variableValues: Record<string, any>,
  runtimeType: GraphQLObjectType,
  selectionSet: SelectionSetNode
): FieldsAndPatches;

/**
 * Collect subfields from a field's selection set
 * @param schema - The GraphQL schema
 * @param fragments - Map of fragment definitions
 * @param variableValues - Variable values for the request
 * @param returnType - The return type of the field
 * @param fieldNode - The field node containing the selection set
 * @returns Collected subfields and patches
 */
function collectSubfields(
  schema: GraphQLSchema,
  fragments: Record<string, FragmentDefinitionNode>,
  variableValues: Record<string, any>,
  returnType: GraphQLOutputType,
  fieldNode: FieldNode
): FieldsAndPatches;

interface FieldsAndPatches {
  fields: Record<string, FieldNode[]>;
  patches: PatchFields[];
}

interface PatchFields {
  label: string;
  fields: Record<string, FieldNode[]>;
}

Usage Examples:

import { collectFields, collectSubfields } from "@graphql-tools/utils";

// Collect fields during execution
const resolveUser = (source, args, context, info) => {
  const { fields } = collectFields(
    info.schema,
    info.fragments,
    info.variableValues,
    info.returnType,
    info.fieldNodes[0].selectionSet
  );
  
  // Optimize database query based on selected fields
  const selectedFields = Object.keys(fields);
  const user = fetchUserWithFields(args.id, selectedFields);
  
  return user;
};

// Collect subfields for nested resolution
const resolveUserPosts = (user, args, context, info) => {
  const postType = info.schema.getType('Post') as GraphQLObjectType;
  const { fields: subfields } = collectSubfields(
    info.schema,
    info.fragments,
    info.variableValues,
    postType,
    info.fieldNodes[0]
  );
  
  return fetchPostsWithFields(user.id, Object.keys(subfields));
};

Schema Iteration

Iterate over schema elements for analysis and transformation.

/**
 * Iterate over all fields in a GraphQL schema
 * @param schema - The schema to iterate over
 * @param fn - Function called for each field
 */
function forEachField(schema: GraphQLSchema, fn: FieldIteratorFn): void;

/**
 * Iterate over all default values in a GraphQL schema
 * @param schema - The schema to iterate over
 * @param fn - Function called for each default value
 */
function forEachDefaultValue(schema: GraphQLSchema, fn: DefaultValueIteratorFn): void;

type FieldIteratorFn = (
  fieldConfig: GraphQLFieldConfig<any, any>,
  fieldName: string,
  typeName: string,
  schema: GraphQLSchema
) => void;

type DefaultValueIteratorFn = (
  type: GraphQLInputType,
  defaultValue: any
) => any;

Usage Examples:

import { forEachField, forEachDefaultValue } from "@graphql-tools/utils";

// Analyze all fields in schema
forEachField(schema, (fieldConfig, fieldName, typeName) => {
  if (!fieldConfig.resolve) {
    console.log(`Field ${typeName}.${fieldName} has no custom resolver`);
  }
  
  // Check for deprecated fields
  if (fieldConfig.deprecationReason) {
    console.log(`Deprecated field: ${typeName}.${fieldName}`);
  }
});

// Process default values
forEachDefaultValue(schema, (type, defaultValue) => {
  console.log(`Default value found:`, defaultValue);
  return defaultValue; // Return processed value
});

Field Manipulation

Modify object type fields programmatically.

/**
 * Append fields to a GraphQL object type
 * @param type - The object type to modify
 * @param newFields - Fields to append
 * @returns New object type with appended fields
 */
function appendObjectFields(
  type: GraphQLObjectType,
  newFields: GraphQLFieldConfigMap<any, any>
): GraphQLObjectType;

/**
 * Remove fields from a GraphQL object type
 * @param type - The object type to modify
 * @param testFn - Function to test which fields to remove
 * @returns New object type with fields removed
 */
function removeObjectFields(
  type: GraphQLObjectType,
  testFn: (fieldName: string, fieldConfig: GraphQLFieldConfig<any, any>) => boolean
): GraphQLObjectType;

/**
 * Select specific fields from a GraphQL object type
 * @param type - The object type to modify
 * @param fieldNames - Names of fields to keep
 * @returns New object type with only selected fields
 */
function selectObjectFields(
  type: GraphQLObjectType,
  fieldNames: string[]
): GraphQLObjectType;

/**
 * Modify fields of a GraphQL object type
 * @param type - The object type to modify
 * @param fn - Function to modify each field
 * @returns New object type with modified fields
 */
function modifyObjectFields(
  type: GraphQLObjectType,
  fn: (
    fieldConfig: GraphQLFieldConfig<any, any>,
    fieldName: string
  ) => GraphQLFieldConfig<any, any> | [string, GraphQLFieldConfig<any, any>] | null | undefined
): GraphQLObjectType;

Usage Examples:

import { 
  appendObjectFields, 
  removeObjectFields, 
  selectObjectFields, 
  modifyObjectFields 
} from "@graphql-tools/utils";
import { GraphQLString } from "graphql";

// Append new fields
const userTypeWithEmail = appendObjectFields(userType, {
  email: {
    type: GraphQLString,
    description: 'User email address'
  }
});

// Remove deprecated fields
const cleanUserType = removeObjectFields(userType, (fieldName, fieldConfig) => {
  return !!fieldConfig.deprecationReason;
});

// Select only specific fields
const publicUserType = selectObjectFields(userType, ['id', 'name', 'avatar']);

// Modify all fields
const userTypeWithLogging = modifyObjectFields(userType, (fieldConfig, fieldName) => {
  const originalResolve = fieldConfig.resolve;
  return {
    ...fieldConfig,
    resolve: (source, args, context, info) => {
      console.log(`Resolving User.${fieldName}`);
      return originalResolve ? originalResolve(source, args, context, info) : source[fieldName];
    }
  };
});

Configuration Conversion

Convert between GraphQL field configurations and runtime representations.

/**
 * Convert a GraphQL field to a field configuration
 * @param field - The field to convert
 * @param type - The parent type
 * @param schema - The schema context
 * @returns Field configuration object
 */
function fieldToFieldConfig(
  field: GraphQLField<any, any>,
  type: GraphQLObjectType | GraphQLInterfaceType,
  schema: GraphQLSchema
): GraphQLFieldConfig<any, any>;

/**
 * Convert a GraphQL argument to an argument configuration
 * @param argument - The argument to convert
 * @returns Argument configuration object
 */
function argumentToArgumentConfig(
  argument: GraphQLArgument
): GraphQLArgumentConfig;

Type Relationships

Analyze type relationships and implementations.

/**
 * Get all object types that implement a given abstract type
 * @param abstractType - The interface or union type
 * @param schema - The GraphQL schema
 * @returns Array of implementing object types
 */
function getImplementingTypes(
  abstractType: GraphQLAbstractType,
  schema: GraphQLSchema
): GraphQLObjectType[];

/**
 * Check if a type implements an abstract type
 * @param schema - The GraphQL schema
 * @param maybeType - The type to check
 * @param superType - The abstract type to check against
 * @returns True if the type implements the abstract type
 */
function implementsAbstractType(
  schema: GraphQLSchema,
  maybeType: GraphQLType,
  superType: GraphQLAbstractType
): boolean;

Usage Examples:

import { getImplementingTypes, implementsAbstractType } from "@graphql-tools/utils";

// Find all types implementing an interface
const nodeInterface = schema.getType('Node') as GraphQLInterfaceType;
const implementingTypes = getImplementingTypes(nodeInterface, schema);
console.log('Types implementing Node:', implementingTypes.map(type => type.name));

// Check if a specific type implements an interface
const userType = schema.getType('User') as GraphQLObjectType;
const implementsNode = implementsAbstractType(schema, userType, nodeInterface);
console.log('User implements Node:', implementsNode);

// Get all types in a union
const searchResultUnion = schema.getType('SearchResult') as GraphQLUnionType;
const unionTypes = getImplementingTypes(searchResultUnion, schema);
console.log('Union member types:', unionTypes.map(type => type.name));

Response Path Utilities

Manage GraphQL execution response paths.

/**
 * Add a path segment to a response path
 * @param prev - Previous path segment
 * @param key - Key to add to path
 * @param typename - Type name for the path segment
 * @returns New path with added segment
 */
function addPath(prev: ResponsePath | undefined, key: string | number, typename?: string): ResponsePath;

/**
 * Convert a response path to an array representation
 * @param path - The response path to convert
 * @returns Array representation of the path
 */
function pathToArray(path: ResponsePath): Array<string | number>;

interface ResponsePath {
  readonly prev: ResponsePath | undefined;
  readonly key: string | number;
  readonly typename?: string;
}

Selection Set Utilities

Parse and analyze GraphQL selection sets.

/**
 * Parse a selection set from a string
 * @param selectionSet - String representation of selection set
 * @returns Parsed selection set node
 */
function parseSelectionSet(selectionSet: string): SelectionSetNode;

/**
 * Check if a type contains a specific selection set
 * @param schema - The GraphQL schema
 * @param type - The type to check
 * @param selectionSet - The selection set to check for
 * @returns True if the type can satisfy the selection set
 */
function typeContainsSelectionSet(
  schema: GraphQLSchema,
  type: GraphQLCompositeType,
  selectionSet: SelectionSetNode
): boolean;

Usage Examples:

import { parseSelectionSet, typeContainsSelectionSet } from "@graphql-tools/utils";

// Parse selection set from string
const selectionSet = parseSelectionSet(`{
  id
  name
  posts {
    title
    content
  }
}`);

// Check if type supports selection
const userType = schema.getType('User') as GraphQLObjectType;
const canResolve = typeContainsSelectionSet(schema, userType, selectionSet);
console.log('User type can resolve selection:', canResolve);