or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-execution.mderror-handling.mdexecution-engine.mdindex.mdlanguage-processing.mdschema-utilities.mdtype-system.mdvalidation-system.md
tile.json

schema-utilities.mddocs/

Schema Utilities

GraphQL.js provides comprehensive utilities for building schemas from SDL, introspection, schema manipulation, comparison, and various transformation operations.

Capabilities

Schema Building from SDL

Build GraphQL schemas from Schema Definition Language strings and AST documents.

/**
 * Build a GraphQL schema from SDL string
 * @param source - SDL string or Source object
 * @param options - Schema building options
 * @returns Executable GraphQL schema
 */
function buildSchema(source: string | Source, options?: BuildSchemaOptions): GraphQLSchema;

/**
 * Build a GraphQL schema from AST document
 * @param documentAST - Parsed SDL document
 * @param options - Schema building options
 * @returns Executable GraphQL schema
 */
function buildASTSchema(documentAST: DocumentNode, options?: BuildSchemaOptions): GraphQLSchema;

interface BuildSchemaOptions {
  /** Treat comment preceding definitions as descriptions */
  commentDescriptions?: boolean;
  /** Assume the SDL is valid and skip some validation */
  assumeValidSDL?: boolean;
  /** Assume the schema will be valid */
  assumeValid?: boolean;
}

Usage Examples:

import { buildSchema, buildASTSchema, parse } from "graphql";

// Build schema from SDL string
const schema = buildSchema(`
  type Query {
    user(id: ID!): User
    posts: [Post!]!
  }
  
  type User {
    id: ID!
    name: String!
    email: String!
    posts: [Post!]!
  }
  
  type Post {
    id: ID!
    title: String!
    content: String!
    author: User!
    publishedAt: String
  }
  
  type Mutation {
    createPost(input: CreatePostInput!): Post!
  }
  
  input CreatePostInput {
    title: String!
    content: String!
    authorId: ID!
  }
`);

// Build schema from parsed AST
const sdlDocument = parse(sdlString);
const schemaFromAST = buildASTSchema(sdlDocument, {
  commentDescriptions: true
});

// Build with options
const optimizedSchema = buildSchema(sdlString, {
  assumeValidSDL: true,  // Skip SDL validation for performance
  assumeValid: true      // Skip schema validation
});

Schema Building from Introspection

Build executable schemas from introspection query results.

/**
 * Build a GraphQL schema from introspection result
 * @param introspection - Introspection query result
 * @param options - Schema building options
 * @returns Executable GraphQL schema
 */
function buildClientSchema(
  introspection: IntrospectionQuery,
  options?: BuildSchemaOptions
): GraphQLSchema;

Usage Examples:

import { buildClientSchema, getIntrospectionQuery, graphql } from "graphql";

// Get introspection from existing schema
const introspectionQuery = getIntrospectionQuery();
const introspectionResult = await graphql({
  schema: existingSchema,
  source: introspectionQuery
});

// Build new schema from introspection
const clientSchema = buildClientSchema(introspectionResult.data as IntrospectionQuery);

// Now clientSchema has the same type structure as existingSchema
// but without resolvers (useful for client-side tools)

// Build with options
const clientSchemaWithOptions = buildClientSchema(introspectionResult.data, {
  assumeValid: true
});

Schema Extension

Extend existing schemas with additional type definitions.

/**
 * Extend an existing GraphQL schema with additional type definitions
 * @param schema - Base schema to extend
 * @param documentAST - SDL document with extensions
 * @param options - Schema building options
 * @returns Extended GraphQL schema
 */
function extendSchema(
  schema: GraphQLSchema,
  documentAST: DocumentNode,
  options?: BuildSchemaOptions
): GraphQLSchema;

Usage Examples:

import { extendSchema, buildSchema, parse } from "graphql";

// Base schema
const baseSchema = buildSchema(`
  type Query {
    user(id: ID!): User
  }
  
  type User {
    id: ID!
    name: String!
  }
`);

// Extension SDL
const extensionSDL = `
  extend type Query {
    posts: [Post!]!
    search(query: String!): [SearchResult!]!
  }
  
  extend type User {
    email: String!
    posts: [Post!]!
  }
  
  type Post {
    id: ID!
    title: String!
    content: String!
    author: User!
  }
  
  union SearchResult = User | Post
`;

// Extend schema
const extensionDocument = parse(extensionSDL);
const extendedSchema = extendSchema(baseSchema, extensionDocument);

// Multiple extensions
const additionalExtensions = parse(`
  extend type Post {
    tags: [String!]!
    publishedAt: String
  }
  
  type Comment {
    id: ID!
    content: String!
    author: User!
    post: Post!
  }
  
  extend type Query {
    comments: [Comment!]!
  }
`);

const fullyExtendedSchema = extendSchema(extendedSchema, additionalExtensions);

Schema Introspection

Generate introspection queries and extract introspection data from schemas.

/**
 * Generate a GraphQL introspection query
 * @param options - Introspection options
 * @returns GraphQL introspection query string
 */
function getIntrospectionQuery(options?: IntrospectionOptions): string;

/**
 * Get introspection result from a schema
 * @param schema - GraphQL schema to introspect
 * @param options - Introspection options
 * @returns Introspection query result
 */
function introspectionFromSchema(
  schema: GraphQLSchema,
  options?: IntrospectionOptions
): IntrospectionQuery;

interface IntrospectionOptions {
  /** Include field and argument descriptions */
  descriptions?: boolean;
  /** Include specifiedByUrl for custom scalars */
  specifiedByUrl?: boolean;
  /** Include isRepeatable flag for directives */
  directiveIsRepeatable?: boolean;
  /** Include schema description */
  schemaDescription?: boolean;
  /** Include deprecation info for input values */
  inputValueDeprecation?: boolean;
}

Usage Examples:

import { 
  getIntrospectionQuery, 
  introspectionFromSchema,
  buildSchema,
  graphql 
} from "graphql";

const schema = buildSchema(`
  """
  User management schema
  """
  type Query {
    """Get user by ID"""
    user(id: ID!): User
  }
  
  """A user in the system"""
  type User {
    id: ID!
    name: String!
    """User's email address"""
    email: String!
  }
`);

// Generate introspection query
const introspectionQuery = getIntrospectionQuery({
  descriptions: true,
  schemaDescription: true
});

// Execute introspection against schema
const result = await graphql({
  schema,
  source: introspectionQuery
});

// Get introspection directly from schema
const introspectionResult = introspectionFromSchema(schema, {
  descriptions: true,
  schemaDescription: true
});

// Minimal introspection for production
const minimalIntrospection = getIntrospectionQuery({
  descriptions: false,
  specifiedByUrl: false
});

Schema Printing

Convert schemas and types back to SDL strings.

/**
 * Print a GraphQL schema as SDL string
 * @param schema - GraphQL schema to print
 * @returns SDL string representation
 */
function printSchema(schema: GraphQLSchema): string;

/**
 * Print a single GraphQL type as SDL
 * @param type - GraphQL type to print
 * @returns SDL string for the type
 */
function printType(type: GraphQLNamedType): string;

/**
 * Print the built-in introspection schema
 * @returns SDL string for introspection schema
 */
function printIntrospectionSchema(): string;

Usage Examples:

import { printSchema, printType, buildSchema } from "graphql";

const schema = buildSchema(`
  type Query {
    user(id: ID!): User
  }
  
  type User {
    id: ID!
    name: String!
    posts: [Post!]!
  }
  
  type Post {
    id: ID!
    title: String!
    author: User!
  }
`);

// Print entire schema
const schemaSDL = printSchema(schema);
console.log(schemaSDL);
/*
type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  author: User!
}
*/

// Print specific type
const userType = schema.getType('User');
const userSDL = printType(userType);
console.log(userSDL);
/*
type User {
  id: ID!
  name: String!
  posts: [Post!]!
}
*/

// Print introspection schema
const introspectionSDL = printIntrospectionSchema();

Schema Transformation

Transform and manipulate existing schemas.

/**
 * Sort schema types and fields lexicographically
 * @param schema - GraphQL schema to sort
 * @returns New schema with sorted elements
 */
function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema;

Usage Examples:

import { lexicographicSortSchema, buildSchema, printSchema } from "graphql";

const schema = buildSchema(`
  type Query {
    zebra: String
    alpha: String
    beta: String
  }
  
  type Zebra {
    id: ID!
  }
  
  type Alpha {
    name: String!
  }
`);

// Sort schema alphabetically
const sortedSchema = lexicographicSortSchema(schema);
const sortedSDL = printSchema(sortedSchema);
console.log(sortedSDL);
/*
type Alpha {
  name: String!
}

type Query {
  alpha: String
  beta: String
  zebra: String
}

type Zebra {
  id: ID!
}
*/

AST and Value Utilities

Convert between AST nodes, GraphQL types, and JavaScript values.

/**
 * Get operation AST from document
 * @param documentAST - GraphQL document
 * @param operationName - Operation name (optional)
 * @returns Operation definition AST or undefined
 */
function getOperationAST(
  documentAST: DocumentNode,
  operationName?: Maybe<string>
): Maybe<OperationDefinitionNode>;

/**
 * Get root type for an operation
 * @param schema - GraphQL schema
 * @param operation - Operation definition AST
 * @returns Root object type for the operation
 */
function getOperationRootType(
  schema: GraphQLSchema,
  operation: OperationDefinitionNode
): GraphQLObjectType;

/**
 * Convert AST type node to GraphQL type
 * @param schema - GraphQL schema
 * @param typeNode - AST type node
 * @returns GraphQL type or undefined
 */
function typeFromAST(
  schema: GraphQLSchema,
  typeNode: TypeNode
): Maybe<GraphQLType>;

/**
 * Convert AST value to JavaScript value
 * @param valueNode - AST value node
 * @param type - GraphQL input type
 * @param variables - Variable values
 * @returns JavaScript value
 */
function valueFromAST(
  valueNode: Maybe<ValueNode>,
  type: GraphQLInputType,
  variables?: Maybe<{ [variable: string]: unknown }>
): unknown;

/**
 * Convert JavaScript value to AST node
 * @param value - JavaScript value
 * @param type - GraphQL input type
 * @returns AST value node or undefined
 */
function astFromValue(
  value: unknown,
  type: GraphQLInputType
): Maybe<ValueNode>;

Usage Examples:

import { 
  getOperationAST,
  getOperationRootType,
  typeFromAST,
  valueFromAST,
  astFromValue,
  parse
} from "graphql";

const document = parse(`
  query GetUser($id: ID!) {
    user(id: $id) { name }
  }
  
  mutation CreateUser($input: CreateUserInput!) {
    createUser(input: $input) { id }
  }
`);

// Get specific operation
const queryOperation = getOperationAST(document, "GetUser");
const mutationOperation = getOperationAST(document); // Gets first operation

// Get root type for operation
const queryRootType = getOperationRootType(schema, queryOperation);
console.log(queryRootType.name); // "Query"

// Convert type AST to GraphQL type
const typeNode = parse('String!').definitions[0].type;
const graphqlType = typeFromAST(schema, typeNode);

// Convert AST value to JavaScript
const valueNode = parse('"hello"').definitions[0];
const jsValue = valueFromAST(valueNode, GraphQLString);
console.log(jsValue); // "hello"

// Convert JavaScript value to AST
const astNode = astFromValue("hello", GraphQLString);
console.log(print(astNode)); // "hello"

Schema Comparison

Compare schemas to find breaking and dangerous changes.

/**
 * Find breaking changes between schemas
 * @param oldSchema - Original schema
 * @param newSchema - New schema to compare
 * @returns Array of breaking changes
 */
function findBreakingChanges(
  oldSchema: GraphQLSchema,
  newSchema: GraphQLSchema
): Array<BreakingChange>;

/**
 * Find dangerous changes between schemas
 * @param oldSchema - Original schema
 * @param newSchema - New schema to compare
 * @returns Array of dangerous changes
 */
function findDangerousChanges(
  oldSchema: GraphQLSchema,
  newSchema: GraphQLSchema
): Array<DangerousChange>;

interface BreakingChange {
  type: BreakingChangeType;
  description: string;
}

interface DangerousChange {
  type: DangerousChangeType;
  description: string;
}

enum BreakingChangeType {
  TYPE_REMOVED = "TYPE_REMOVED",
  TYPE_CHANGED_KIND = "TYPE_CHANGED_KIND",
  TYPE_REMOVED_FROM_UNION = "TYPE_REMOVED_FROM_UNION",
  VALUE_REMOVED_FROM_ENUM = "VALUE_REMOVED_FROM_ENUM",
  REQUIRED_INPUT_FIELD_ADDED = "REQUIRED_INPUT_FIELD_ADDED",
  IMPLEMENTED_INTERFACE_REMOVED = "IMPLEMENTED_INTERFACE_REMOVED",
  FIELD_REMOVED = "FIELD_REMOVED",
  FIELD_CHANGED_KIND = "FIELD_CHANGED_KIND",
  REQUIRED_ARG_ADDED = "REQUIRED_ARG_ADDED",
  ARG_REMOVED = "ARG_REMOVED",
  ARG_CHANGED_KIND = "ARG_CHANGED_KIND",
  DIRECTIVE_REMOVED = "DIRECTIVE_REMOVED",
  DIRECTIVE_ARG_REMOVED = "DIRECTIVE_ARG_REMOVED",
  REQUIRED_DIRECTIVE_ARG_ADDED = "REQUIRED_DIRECTIVE_ARG_ADDED",
  DIRECTIVE_REPEATABLE_REMOVED = "DIRECTIVE_REPEATABLE_REMOVED",
  DIRECTIVE_LOCATION_REMOVED = "DIRECTIVE_LOCATION_REMOVED"
}

enum DangerousChangeType {
  ARG_ADDED = "ARG_ADDED",
  VALUE_ADDED_TO_ENUM = "VALUE_ADDED_TO_ENUM",
  INTERFACE_ADDED_TO_OBJECT = "INTERFACE_ADDED_TO_OBJECT",
  TYPE_ADDED_TO_UNION = "TYPE_ADDED_TO_UNION",
  OPTIONAL_INPUT_FIELD_ADDED = "OPTIONAL_INPUT_FIELD_ADDED",
  OPTIONAL_ARG_ADDED = "OPTIONAL_ARG_ADDED",
  IMPLEMENTED_INTERFACE_ADDED = "IMPLEMENTED_INTERFACE_ADDED"
}

Usage Examples:

import { 
  findBreakingChanges,
  findDangerousChanges,
  buildSchema 
} from "graphql";

const oldSchema = buildSchema(`
  type Query {
    user(id: ID!): User
  }
  
  type User {
    id: ID!
    name: String!
    email: String!
  }
  
  enum Status {
    ACTIVE
    INACTIVE
  }
`);

const newSchema = buildSchema(`
  type Query {
    user(id: ID!, includeEmail: Boolean = false): User
  }
  
  type User {
    id: ID!
    name: String!
    email: String
    profile: Profile
  }
  
  type Profile {
    bio: String
  }
  
  enum Status {
    ACTIVE
    INACTIVE
    PENDING
  }
`);

// Find breaking changes
const breakingChanges = findBreakingChanges(oldSchema, newSchema);
console.log(breakingChanges);
/*
[
  {
    type: "FIELD_CHANGED_KIND",
    description: "User.email changed type from String! to String"
  }
]
*/

// Find dangerous changes
const dangerousChanges = findDangerousChanges(oldSchema, newSchema);
console.log(dangerousChanges);
/*
[
  {
    type: "ARG_ADDED",
    description: "An optional argument includeEmail was added to Query.user"
  },
  {
    type: "VALUE_ADDED_TO_ENUM", 
    description: "PENDING was added to enum Status"
  }
]
*/

// Use in CI/CD pipeline
const validateSchemaChanges = (oldSchema, newSchema) => {
  const breaking = findBreakingChanges(oldSchema, newSchema);
  const dangerous = findDangerousChanges(oldSchema, newSchema);
  
  if (breaking.length > 0) {
    console.error("Breaking changes detected:");
    breaking.forEach(change => console.error(`- ${change.description}`));
    process.exit(1);
  }
  
  if (dangerous.length > 0) {
    console.warn("Dangerous changes detected:");
    dangerous.forEach(change => console.warn(`- ${change.description}`));
  }
  
  console.log("Schema changes validated successfully");
};

Additional Utilities

Other useful schema manipulation utilities.

/**
 * Coerce input value to GraphQL type
 * @param inputValue - Value to coerce
 * @param type - GraphQL input type
 * @param onError - Error callback
 * @returns Coerced value
 */
function coerceInputValue(
  inputValue: unknown,
  type: GraphQLInputType,
  onError?: (path: ReadonlyArray<string | number>, invalidValue: unknown, error: GraphQLError) => void
): unknown;

/**
 * Validate GraphQL schema and return array of errors
 * @param schema - GraphQL schema to validate
 * @returns Array of validation errors
 */
function validateSchema(schema: GraphQLSchema): ReadonlyArray<GraphQLError>;

/**
 * Validate GraphQL schema and throw on errors
 * @param schema - GraphQL schema to validate
 * @throws Error if schema has validation errors
 */
function assertValidSchema(schema: GraphQLSchema): void;

/**
 * Assert that a string is a valid GraphQL name
 * @param name - Name to validate
 * @returns The validated name
 * @throws GraphQLError if name is invalid
 */
function assertName(name: string): string;

/**
 * Assert that a string is a valid GraphQL enum value name
 * @param name - Enum value name to validate
 * @returns The validated name
 * @throws GraphQLError if name is invalid
 */
function assertEnumValueName(name: string): string;

/**
 * Resolve a thunk that returns a readonly array
 * @param thunk - Function or array to resolve
 * @returns Resolved readonly array
 */
function resolveReadonlyArrayThunk<T>(thunk: ThunkReadonlyArray<T>): ReadonlyArray<T>;

/**
 * Resolve a thunk that returns an object map
 * @param thunk - Function or object map to resolve
 * @returns Resolved object map
 */
function resolveObjMapThunk<T>(thunk: ThunkObjMap<T>): ThunkObjMap<T>;

/**
 * Check if two types are equal
 * @param typeA - First type
 * @param typeB - Second type
 * @returns True if types are equal
 */
function isEqualType(typeA: GraphQLType, typeB: GraphQLType): boolean;

/**
 * Check if type is subtype of another
 * @param schema - GraphQL schema
 * @param maybeSubType - Potential subtype
 * @param superType - Super type
 * @returns True if subtype relationship exists
 */
function isTypeSubTypeOf(
  schema: GraphQLSchema,
  maybeSubType: GraphQLType,
  superType: GraphQLType
): boolean;

/**
 * Check if two composite types can overlap
 * @param schema - GraphQL schema
 * @param typeA - First composite type
 * @param typeB - Second composite type
 * @returns True if types can overlap
 */
function doTypesOverlap(
  schema: GraphQLSchema,
  typeA: GraphQLCompositeType,
  typeB: GraphQLCompositeType
): boolean;