or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

caching-performance.mdcontext-types.mderror-handling.mdindex.mdlogging-system.mdplugin-system.mdrequest-processing.mdresult-processing.mdschema-management.mdserver-configuration.mdsubscription-system.md
tile.json

context-types.mddocs/

Context and Types

Type-safe context system with initial context setup, user context extension, comprehensive TypeScript support for server and user context types, and utility type definitions.

Capabilities

Initial Context Interface

Core context interface provided to all GraphQL operations containing request information and parameters.

/**
 * Initial context interface available to all GraphQL operations
 */
interface YogaInitialContext extends ServerAdapterInitialContext {
  /** Parsed GraphQL parameters from the request */
  params: GraphQLParams;
  /** Original HTTP request object */
  request: Request;
}

Server Adapter Context

Base context interface from the server adapter providing core server functionality.

/**
 * Server adapter initial context (from @whatwg-node/server)
 */
interface ServerAdapterInitialContext {
  /** Server adapter request object */
  request: Request;
  /** Server adapter fetch API */
  fetch: typeof fetch;
  /** Server adapter URL utilities */
  url: URL;
  /** Environment variables */
  env?: Record<string, string>;
  /** Execution context for serverless environments */
  executionContext?: any;
  /** Additional server context properties */
  [key: string]: any;
}

CORS Configuration Types

Type definitions for Cross-Origin Resource Sharing configuration.

/**
 * CORS configuration options
 */
type CORSOptions =
  | {
      /** Allowed origins - string, array of strings, or function */
      origin?: string[] | string | ((origin: string) => boolean);
      /** Allowed HTTP methods */
      methods?: string[];
      /** Allowed request headers */
      allowedHeaders?: string[];
      /** Headers exposed to the client */
      exposedHeaders?: string[];
      /** Allow credentials in CORS requests */
      credentials?: boolean;
      /** Preflight response cache duration in seconds */
      maxAge?: number;
      /** Enable CORS preflight for simple requests */
      preflightContinue?: boolean;
      /** Provide options to next handler */
      optionsSuccessStatus?: number;
    }
  | false; // Disable CORS entirely

Fetch API Types

Type definitions for the Fetch API implementation used by GraphQL Yoga.

/**
 * Fetch API implementation type (from @whatwg-node/fetch)
 */
type FetchAPI = ReturnType<typeof createFetch>;

/**
 * Fetch event interface for service worker environments
 */
interface FetchEvent extends Event {
  /** The fetch request */
  request: Request;
  /** Respond with a response or promise */
  respondWith(response: Response | Promise<Response>): void;
  /** Wait until promise resolves */
  waitUntil(promise: Promise<any>): void;
}

Utility Types

General utility types used throughout the GraphQL Yoga API.

/**
 * Type that can be a single value or an array
 */
type MaybeArray<T> = T | T[];

/**
 * Type that can be a value or a promise
 */
type PromiseOrValue<T> = T | Promise<T>;

/**
 * Optional type utility
 */
type Optional<T> = T | undefined;

/**
 * Maybe type utility (includes null)
 */
type Maybe<T> = T | null | undefined;

/**
 * Spread utility type for object merging
 */
type Spread<T> = T extends (...args: any[]) => any
  ? T
  : T extends ReadonlyArray<any>
  ? { [K in keyof T]: T[K] }
  : T extends object
  ? { [K in keyof T]: T[K] }
  : T;

/**
 * Async iterable iterator or direct value
 */
type AsyncIterableIteratorOrValue<T> = AsyncIterableIterator<T> | T;

GraphQL HTTP Extensions

Interface for HTTP-specific extensions in GraphQL responses.

/**
 * HTTP-specific extensions for GraphQL responses
 */
interface GraphQLHTTPExtensions {
  /** HTTP status code for the response */
  status?: number;
  /** Additional HTTP headers to include */
  headers?: Record<string, string>;
  /** HTTP status text */
  statusText?: string;
}

Context Factory Types

Type definitions for context creation and extension.

/**
 * Context factory function type for creating user context
 */
type ContextFactory<TServerContext, TUserContext> = (
  initialContext: YogaInitialContext & TServerContext
) => PromiseOrValue<TUserContext>;

/**
 * Context extension function type
 */
type ContextExtension<TContext, TExtension> = (
  context: TContext
) => PromiseOrValue<TExtension>;

Disposal and Cleanup

Types for resource disposal and cleanup in server environments.

/**
 * Disposal symbols for resource cleanup (from @whatwg-node/server)
 */
declare const DisposableSymbols: {
  dispose: symbol;
  asyncDispose: symbol;
};

/**
 * Disposable resource interface
 */
interface Disposable {
  [DisposableSymbols.dispose](): void;
}

/**
 * Async disposable resource interface
 */
interface AsyncDisposable {
  [DisposableSymbols.asyncDispose](): Promise<void>;
}

Usage Examples:

import { 
  createYoga,
  YogaInitialContext,
  CORSOptions,
  MaybeArray,
  PromiseOrValue
} from 'graphql-yoga';

// Basic context setup
interface MyServerContext {
  database: Database;
  logger: Logger;
}

interface MyUserContext {
  user?: User;
  permissions: string[];
}

const yoga = createYoga<MyServerContext, MyUserContext>({
  schema: mySchema,
  context: async ({ request, params }) => {
    // Extract user from request
    const token = request.headers.get('authorization');
    const user = token ? await validateToken(token) : null;
    
    return {
      user,
      permissions: user ? await getUserPermissions(user.id) : []
    };
  }
});

// Advanced context with server context
const advancedYoga = createYoga<MyServerContext, MyUserContext>({
  schema: mySchema,
  context: async (initialContext) => {
    const { request, params } = initialContext;
    const { database, logger } = initialContext; // Server context
    
    logger.info('Processing request', { 
      operation: params.operationName,
      userAgent: request.headers.get('user-agent')
    });
    
    // Authenticate user
    const authHeader = request.headers.get('authorization');
    let user: User | undefined;
    
    if (authHeader?.startsWith('Bearer ')) {
      const token = authHeader.slice(7);
      user = await database.users.findByToken(token);
    }
    
    // Get user permissions
    const permissions = user 
      ? await database.permissions.findByUserId(user.id)
      : [];
    
    return { user, permissions };
  }
});

// CORS configuration examples
const corsOptions: CORSOptions = {
  origin: ['http://localhost:3000', 'https://myapp.com'],
  methods: ['GET', 'POST'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  exposedHeaders: ['X-Request-ID'],
  credentials: true,
  maxAge: 86400 // 24 hours
};

const corsYoga = createYoga({
  schema: mySchema,
  cors: corsOptions
});

// Dynamic CORS configuration
const dynamicCorsYoga = createYoga({
  schema: mySchema,
  cors: {
    origin: (origin) => {
      // Allow all localhost origins in development
      if (process.env.NODE_ENV === 'development') {
        return origin.includes('localhost');
      }
      // Strict whitelist in production
      return ['https://myapp.com', 'https://admin.myapp.com'].includes(origin);
    },
    credentials: true
  }
});

// Context with type utilities
function createContextFactory<T>(): ContextFactory<{}, T> {
  return (initialContext): PromiseOrValue<T> => {
    // Implementation
    return {} as T;
  };
}

// Using utility types in resolvers
const resolvers = {
  Query: {
    users: (): MaybeArray<User> => {
      // Can return single user or array
      return [{ id: '1', name: 'Alice' }];
    },
    
    asyncData: async (): PromiseOrValue<string> => {
      // Can return value directly or promise
      return 'data';
    },
    
    optionalUser: (): Optional<User> => {
      // May return undefined
      return undefined;
    }
  }
};

// Context extension plugin
function useContextExtension<T>(extension: T): Plugin {
  return {
    onParams({ setParams, params }) {
      setParams({
        ...params,
        extensions: {
          ...params.extensions,
          contextExtension: extension
        }
      });
    }
  };
}

// Multi-tenant context
interface TenantContext {
  tenantId: string;
  tenantConfig: TenantConfig;
}

const multiTenantYoga = createYoga<{}, TenantContext>({
  schema: mySchema,
  context: async ({ request }) => {
    // Extract tenant from subdomain or header
    const host = request.headers.get('host') || '';
    const tenantId = host.split('.')[0];
    
    if (!tenantId) {
      throw new Error('Tenant not specified');
    }
    
    const tenantConfig = await getTenantConfig(tenantId);
    
    return {
      tenantId,
      tenantConfig
    };
  }
});

// Request context enrichment
function enrichContext<T extends YogaInitialContext>(
  baseContext: T
): T & { enriched: true } {
  return {
    ...baseContext,
    enriched: true
  };
}

// Context validation
function validateContext<T>(context: T): asserts context is T {
  if (!context) {
    throw new Error('Context is required');
  }
}

// Context with cleanup resources  
interface ResourceContext {
  database: Database;
  cache: Cache;
}

class DatabaseConnection implements AsyncDisposable {
  async [DisposableSymbols.asyncDispose](): Promise<void> {
    await this.close();
  }
  
  async close(): Promise<void> {
    // Cleanup database connection
  }
}

const resourceYoga = createYoga<ResourceContext, {}>({
  schema: mySchema,
  context: async () => {
    const database = new DatabaseConnection();
    const cache = new CacheConnection();
    
    return { database, cache };
  }
});

// Type-safe context access in resolvers
const typedResolvers = {
  Query: {
    me: (
      _: any,
      __: any,
      context: YogaInitialContext & MyUserContext
    ): User | null => {
      // TypeScript knows context has user and permissions
      return context.user || null;
    },
    
    secureData: (
      _: any,
      __: any,
      context: YogaInitialContext & MyUserContext
    ): string => {
      if (!context.user) {
        throw new Error('Authentication required');
      }
      
      if (!context.permissions.includes('READ_SECURE_DATA')) {
        throw new Error('Insufficient permissions');
      }
      
      return 'Secret data';
    }
  }
};