or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cache-management.mdcache-storage.mdfragment-matching.mdindex.mdoptimistic-updates.mdstore-operations.md
tile.json

fragment-matching.mddocs/

Fragment Matching

GraphQL fragment matching system for handling fragments on unions, interfaces, and complex query structures with different levels of type information.

Capabilities

HeuristicFragmentMatcher

Basic fragment matcher using heuristic matching for fragments when detailed type information is unavailable.

/**
 * Basic fragment matcher that uses heuristic approach
 * Works well for simple cases but limited with unions/interfaces
 * Provides warnings when encountering complex fragment scenarios
 */
class HeuristicFragmentMatcher implements FragmentMatcherInterface {
  /**
   * Creates a new heuristic fragment matcher
   * No configuration required - ready to use immediately
   */
  constructor();

  /**
   * Always ready - no initialization required
   * @returns Promise resolving immediately
   */
  ensureReady(): Promise<void>;

  /**
   * Can bypass initialization - no setup needed
   * @returns Always true
   */
  canBypassInit(): boolean;

  /**
   * Matches fragments using heuristic approach
   * @param idValue - Object identifier to match against
   * @param typeCondition - GraphQL type condition from fragment
   * @param context - Read context containing store and config
   * @returns true if matches, false if doesn't match, 'heuristic' if uncertain
   */
  match(
    idValue: IdValue,
    typeCondition: string,
    context: ReadStoreContext
  ): boolean | 'heuristic';
}

Usage Example:

import { InMemoryCache, HeuristicFragmentMatcher } from "apollo-cache-inmemory";

const cache = new InMemoryCache({
  fragmentMatcher: new HeuristicFragmentMatcher()
});

// Works well with simple fragments
const query = gql`
  query GetUser {
    user {
      id
      name
      ... on PremiumUser {
        subscriptionLevel
      }
    }
  }
`;

IntrospectionFragmentMatcher

Advanced fragment matcher using GraphQL introspection data for precise union and interface fragment matching.

/**
 * Advanced fragment matcher using introspection data
 * Provides precise matching for unions and interfaces
 * Requires introspection query result for configuration
 */
class IntrospectionFragmentMatcher implements FragmentMatcherInterface {
  /**
   * Creates introspection-based fragment matcher
   * @param options - Configuration including introspection data
   */
  constructor(options?: {
    introspectionQueryResultData?: IntrospectionResultData;
  });

  /**
   * Matches fragments using introspection type information
   * @param idValue - Object identifier to match against
   * @param typeCondition - GraphQL type condition from fragment
   * @param context - Read context containing store and config
   * @returns true if fragment matches, false otherwise
   */
  match(
    idValue: IdValue,
    typeCondition: string,
    context: ReadStoreContext
  ): boolean;
}

Usage Example:

import { 
  InMemoryCache, 
  IntrospectionFragmentMatcher,
  IntrospectionResultData 
} from "apollo-cache-inmemory";

// First, obtain introspection data from your GraphQL server
const introspectionQueryResultData: IntrospectionResultData = {
  __schema: {
    types: [
      {
        kind: "INTERFACE",
        name: "Node",
        possibleTypes: [
          { name: "User" },
          { name: "Post" }
        ]
      },
      {
        kind: "UNION", 
        name: "SearchResult",
        possibleTypes: [
          { name: "User" },
          { name: "Post" },
          { name: "Comment" }
        ]
      }
    ]
  }
};

const fragmentMatcher = new IntrospectionFragmentMatcher({
  introspectionQueryResultData
});

const cache = new InMemoryCache({
  fragmentMatcher
});

// Now fragments on unions/interfaces work correctly
const query = gql`
  query Search($term: String!) {
    search(term: $term) {
      ... on User {
        id
        name
        email
      }
      ... on Post {
        id
        title
        content
      }
    }
  }
`;

Fragment Matcher Interface

Core interface that all fragment matchers must implement.

interface FragmentMatcherInterface {
  /**
   * Determines if a fragment matches an object in the cache
   * @param idValue - Identifier of the object to test
   * @param typeCondition - GraphQL type condition from the fragment
   * @param context - Context containing cache store and configuration
   * @returns true if match, false if no match, 'heuristic' if uncertain
   */
  match(
    idValue: IdValue,
    typeCondition: string,
    context: ReadStoreContext
  ): boolean | 'heuristic';
}

Introspection Query

Pre-built GraphQL introspection query for obtaining type information needed by IntrospectionFragmentMatcher.

/**
 * GraphQL introspection query document for fragment matching
 * Query to run against your GraphQL server to get type information
 * Export is the complete DocumentNode ready to execute
 * Default export from 'apollo-cache-inmemory/lib/fragmentMatcherIntrospectionQuery'
 */
const introspectionQuery: DocumentNode;

Usage Example:

import introspectionQuery from "apollo-cache-inmemory/lib/fragmentMatcherIntrospectionQuery";
import { ApolloClient } from "apollo-client";

// Execute introspection query against your server
async function getIntrospectionData(client: ApolloClient<any>) {
  const result = await client.query({
    query: introspectionQuery,
    // Disable cache for introspection
    fetchPolicy: 'network-only'
  });
  
  return result.data;
}

// Use the result with IntrospectionFragmentMatcher
getIntrospectionData(client).then(introspectionResultData => {
  const fragmentMatcher = new IntrospectionFragmentMatcher({
    introspectionQueryResultData: introspectionResultData
  });
  
  const cache = new InMemoryCache({ fragmentMatcher });
});

Types

interface ReadStoreContext {
  readonly store: NormalizedCache;
  readonly cacheRedirects: CacheResolverMap;
  readonly dataIdFromObject?: IdGetter;
}

interface IntrospectionResultData {
  __schema: {
    types: {
      kind: string;
      name: string;
      possibleTypes: {
        name: string;
      }[];
    }[];
  };
}

type PossibleTypesMap = { 
  [key: string]: string[] 
};

interface IdValue {
  type: "id";
  id: string;
  generated: boolean;
}

Best Practices

When to Use Each Fragment Matcher

Use HeuristicFragmentMatcher when:

  • Simple schema without unions or interfaces
  • Prototyping or development phase
  • Fragments only on concrete types
  • Performance is critical and exact matching isn't required

Use IntrospectionFragmentMatcher when:

  • Schema contains unions or interfaces
  • Fragments are used on abstract types
  • Exact fragment matching is required
  • Production applications with complex schemas

Obtaining Introspection Data

// Method 1: Manual introspection query
import introspectionQuery from "apollo-cache-inmemory/lib/fragmentMatcherIntrospectionQuery";

const client = new ApolloClient({ ... });
const { data } = await client.query({ 
  query: introspectionQuery 
});

// Method 2: Using Apollo CLI
// Run: apollo client:codegen --target=typescript --includes="./src/**/*.{ts,tsx}" --excludes="./src/**/__tests__/**/*"

// Method 3: Build-time generation
// Add to your build process to fetch introspection data
// and generate static fragment matcher configuration