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

execution-engine.mddocs/

Execution Engine

The execution engine provides runtime execution of GraphQL operations with support for async resolvers, subscriptions, field resolution strategies, and value coercion.

Capabilities

Operation Execution

Execute GraphQL operations with comprehensive resolver support and error handling.

/**
 * Execute a GraphQL operation
 * @param args - Execution arguments
 * @returns Promise resolving to execution result
 */
function execute(args: ExecutionArgs): PromiseOrValue<ExecutionResult>;

/**
 * Execute a GraphQL operation synchronously
 * @param args - Execution arguments  
 * @returns Execution result (throws if any async resolvers)
 */
function executeSync(args: ExecutionArgs): ExecutionResult;

interface ExecutionArgs {
  /** GraphQL schema to execute against */
  schema: GraphQLSchema;
  /** Parsed GraphQL document to execute */
  document: DocumentNode;
  /** Root value passed to top-level resolvers */
  rootValue?: unknown;
  /** Context value passed to all resolvers */
  contextValue?: unknown;
  /** Variable values for the operation */
  variableValues?: Maybe<{ readonly [variable: string]: unknown }>;
  /** Operation name to execute (if document has multiple) */
  operationName?: Maybe<string>;
  /** Custom field resolver function */
  fieldResolver?: Maybe<GraphQLFieldResolver<any, any>>;
  /** Custom type resolver for abstract types */
  typeResolver?: Maybe<GraphQLTypeResolver<any, any>>;
  /** Custom subscription field resolver */
  subscribeFieldResolver?: Maybe<GraphQLFieldResolver<any, any>>;
}

interface ExecutionResult {
  /** Execution errors */
  errors?: ReadonlyArray<GraphQLError>;
  /** Result data */
  data?: { [key: string]: unknown } | null;
  /** Extension data */
  extensions?: { [key: string]: unknown };
}

Usage Examples:

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

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

const document = parse(`
  query GetUserWithPosts($userId: ID!) {
    user(id: $userId) {
      id
      name
      posts {
        id
        title
      }
    }
  }
`);

// Execute with context and variables
const result = await execute({
  schema,
  document,
  variableValues: { userId: "123" },
  contextValue: { 
    db: database,
    currentUser: currentUser 
  },
  rootValue: {
    user: async ({ id }, args, { db }) => {
      return await db.users.findById(id);
    },
    posts: async (root, args, { db }) => {
      return await db.posts.findAll();
    }
  }
});

console.log(result.data);
// { user: { id: "123", name: "Alice", posts: [...] } }

Subscription Execution

Execute GraphQL subscriptions that return async iterators of results.

/**
 * Execute a GraphQL subscription
 * @param args - Execution arguments
 * @returns Promise resolving to async iterator of results or error result
 */
function subscribe(args: ExecutionArgs): Promise<AsyncIterator<ExecutionResult> | ExecutionResult>;

/**
 * Create the initial event stream for a subscription
 * @param args - Execution arguments
 * @returns Promise resolving to async iterable or error result
 */
function createSourceEventStream(args: ExecutionArgs): Promise<AsyncIterable<unknown> | ExecutionResult>;

Usage Examples:

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

const schema = buildSchema(`
  type Subscription {
    messageAdded(channel: String!): Message!
  }
  
  type Message {
    id: ID!
    content: String!
    user: String!
    timestamp: String!
  }
`);

const document = parse(`
  subscription MessageSub($channel: String!) {
    messageAdded(channel: $channel) {
      id
      content
      user
      timestamp
    }
  }
`);

// Execute subscription
const subscriptionResult = await subscribe({
  schema,
  document,
  variableValues: { channel: "general" },
  rootValue: {
    messageAdded: async function* ({ channel }) {
      // Subscribe to message events
      const eventStream = messageEmitter.subscribe(channel);
      
      for await (const message of eventStream) {
        yield message;
      }
    }
  }
});

if (Symbol.asyncIterator in subscriptionResult) {
  // Handle subscription results
  for await (const result of subscriptionResult) {
    console.log('New message:', result.data);
  }
} else {
  // Handle subscription error
  console.error('Subscription failed:', subscriptionResult.errors);
}

Default Resolvers

Built-in resolver functions for common resolution patterns.

/**
 * Default field resolver - resolves fields from source object properties
 * @param source - Source object from parent resolver
 * @param args - Field arguments
 * @param contextValue - Context value
 * @param info - Resolver info object
 * @returns Resolved field value
 */
function defaultFieldResolver(
  source: any,
  args: any,
  contextValue: any,
  info: GraphQLResolveInfo
): any;

/**
 * Default type resolver for abstract types
 * @param value - Value returned from field resolver
 * @param contextValue - Context value
 * @param info - Resolver info object  
 * @param abstractType - Abstract type being resolved
 * @returns Type name string or undefined
 */
function defaultTypeResolver(
  value: any,
  contextValue: any,
  info: GraphQLResolveInfo,
  abstractType: GraphQLAbstractType
): PromiseOrValue<string | undefined>;

Usage Examples:

import { defaultFieldResolver, defaultTypeResolver } from "graphql";

// Custom field resolver that falls back to default behavior
const customFieldResolver = (source, args, context, info) => {
  // Add logging
  console.log(`Resolving field: ${info.fieldName}`);
  
  // Custom logic for specific fields
  if (info.fieldName === 'computedValue') {
    return computeSpecialValue(source, args);
  }
  
  // Use default resolver for other fields
  return defaultFieldResolver(source, args, context, info);
};

// Use in schema execution
const result = await execute({
  schema,
  document,
  fieldResolver: customFieldResolver
});

Value Resolution Utilities

Utilities for resolving arguments, variables, and directive values.

/**
 * Resolve field or directive arguments
 * @param def - Field or directive definition
 * @param node - AST node (field or directive)
 * @param variableValues - Variable values map
 * @returns Resolved argument values
 */
function getArgumentValues(
  def: GraphQLField<any, any> | GraphQLDirective,
  node: FieldNode | DirectiveNode,
  variableValues?: Maybe<{ readonly [variable: string]: unknown }>
): CoercedVariableValues;

/**
 * Resolve operation variable values
 * @param schema - GraphQL schema
 * @param varDefNodes - Variable definition AST nodes
 * @param inputs - Input variable values
 * @returns Coerced variable values
 */
function getVariableValues(
  schema: GraphQLSchema,
  varDefNodes: ReadonlyArray<VariableDefinitionNode>,
  inputs: Maybe<{ [key: string]: unknown }>
): CoercedVariableValues;

/**
 * Extract directive values from AST node
 * @param directiveDef - Directive definition
 * @param node - AST node
 * @param variableValues - Variable values map
 * @returns Directive argument values or undefined
 */
function getDirectiveValues(
  directiveDef: GraphQLDirective,
  node: ASTNode,
  variableValues?: Maybe<{ readonly [variable: string]: unknown }>
): undefined | { [key: string]: unknown };

interface CoercedVariableValues {
  /** Successfully coerced values */
  coerced: { [key: string]: unknown };
  /** Errors encountered during coercion */
  errors?: ReadonlyArray<GraphQLError>;
}

Usage Examples:

import { 
  getArgumentValues, 
  getVariableValues, 
  getDirectiveValues 
} from "graphql";

// In a custom field resolver
const customResolver = (source, args, context, info) => {
  // Get processed argument values
  const argValues = getArgumentValues(
    info.fieldNodes[0], 
    info.variableValues
  );
  
  // Check for specific directive
  const deprecatedDirective = info.schema.getDirective('deprecated');
  const deprecationInfo = getDirectiveValues(
    deprecatedDirective,
    info.fieldNodes[0],
    info.variableValues
  );
  
  if (deprecationInfo) {
    console.warn(`Using deprecated field: ${deprecationInfo.reason}`);
  }
  
  return processField(source, argValues);
};

Response Path Utilities

Utilities for working with response paths in execution results.

/**
 * Convert response path to array format
 * @param path - Response path object
 * @returns Array of path segments
 */
function responsePathAsArray(path: ResponsePath): ReadonlyArray<string | number>;

interface ResponsePath {
  /** Previous path segment */
  readonly prev: ResponsePath | undefined;
  /** Current path key */
  readonly key: string | number;
  /** Type name for this path segment */
  readonly typename: string | undefined;
}

Usage Examples:

import { responsePathAsArray } from "graphql";

// In field resolver or error handler
const resolver = (source, args, context, info) => {
  try {
    return processField(source, args);
  } catch (error) {
    // Convert path for error reporting
    const pathArray = responsePathAsArray(info.path);
    console.error(`Error at path ${pathArray.join('.')}: ${error.message}`);
    throw error;
  }
};

Resolver Information

GraphQLResolveInfo

Comprehensive information object passed to field resolvers.

interface GraphQLResolveInfo {
  /** Name of the field being resolved */
  readonly fieldName: string;
  /** AST nodes for this field selection */
  readonly fieldNodes: ReadonlyArray<FieldNode>;
  /** GraphQL return type for this field */
  readonly returnType: GraphQLOutputType;
  /** GraphQL parent type containing this field */
  readonly parentType: GraphQLObjectType;
  /** Response path to this field */
  readonly path: ResponsePath;
  /** GraphQL schema being executed */
  readonly schema: GraphQLSchema;
  /** Fragment definitions from the document */
  readonly fragments: { [fragmentName: string]: FragmentDefinitionNode };
  /** Root value for the operation */
  readonly rootValue: unknown;
  /** Operation definition being executed */
  readonly operation: OperationDefinitionNode;
  /** Resolved variable values */
  readonly variableValues: { [variableName: string]: unknown };
}

Execution Context Types

type GraphQLFieldResolver<TSource = any, TContext = any, TArgs = any, TReturn = any> = (
  source: TSource,
  args: TArgs,
  context: TContext,
  info: GraphQLResolveInfo
) => TReturn;

type GraphQLTypeResolver<TSource = any, TContext = any, TReturn = PromiseOrValue<string | undefined>> = (
  value: TSource,
  context: TContext,
  info: GraphQLResolveInfo,
  abstractType: GraphQLAbstractType
) => TReturn;

type PromiseOrValue<T> = Promise<T> | T;
type Maybe<T> = T | null | undefined;
type ObjMap<T> = { [key: string]: T };