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

cache-management.mddocs/

Core Cache Management

Primary cache functionality for storing, retrieving, and manipulating normalized GraphQL data with automatic normalization and denormalization.

Capabilities

InMemoryCache Class

Main cache implementation providing normalized data storage and GraphQL query processing.

/**
 * Main cache implementation for Apollo Client providing normalized data storage
 * Extends ApolloCache to provide GraphQL-specific caching functionality
 */
class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
  /**
   * Creates a new InMemoryCache instance
   * @param config - Optional configuration object
   */
  constructor(config?: InMemoryCacheConfig);

  /**
   * Restores cache state from a serialized object
   * @param data - Normalized cache data to restore
   * @returns This cache instance for chaining
   */
  restore(data: NormalizedCacheObject): this;

  /**
   * Extracts current cache state as a serializable object
   * @param optimistic - Whether to include optimistic data (default: false)
   * @returns Serialized cache state
   */
  extract(optimistic?: boolean): NormalizedCacheObject;

  /**
   * Reads data from cache using a GraphQL query
   * @param options - Query options including query document and variables
   * @returns Query result or null if not found
   */
  read<T>(options: Cache.ReadOptions): T | null;

  /**
   * Writes data to cache from a GraphQL query result
   * @param write - Write options including query, result, and variables
   */
  write(write: Cache.WriteOptions): void;

  /**
   * Compares query against current cache state
   * @param query - Diff options including query and variables
   * @returns Diff result indicating completeness and data changes
   */
  diff<T>(query: Cache.DiffOptions): Cache.DiffResult<T>;

  /**
   * Watches cache for changes to a specific query
   * @param watch - Watch options including query and callback
   * @returns Function to stop watching
   */
  watch(watch: Cache.WatchOptions): () => void;

  /**
   * Evicts data from cache (NOT IMPLEMENTED - throws InvariantError)
   * This method is inherited from ApolloCache but not implemented in InMemoryCache
   * Calling this method will throw an error: "eviction is not implemented on InMemory Cache"
   * @param query - Eviction query options  
   * @throws InvariantError Always throws - eviction not supported
   */
  evict(query: Cache.EvictOptions): never;

  /**
   * Resets cache to empty state
   * @returns Promise resolving when reset is complete
   */
  reset(): Promise<void>;

  /**
   * Removes specific optimistic update layer
   * @param idToRemove - ID of optimistic update to remove
   */
  removeOptimistic(idToRemove: string): void;

  /**
   * Performs transaction with optional optimistic layer
   * @param transaction - Transaction function to execute
   * @param optimisticId - Optional ID for optimistic transaction
   */
  performTransaction(
    transaction: Transaction<NormalizedCacheObject>,
    optimisticId?: string
  ): void;

  /**
   * Records optimistic transaction with specific ID
   * @param transaction - Transaction function to execute
   * @param id - ID for the optimistic transaction
   */
  recordOptimisticTransaction(
    transaction: Transaction<NormalizedCacheObject>,
    id: string
  ): void;

  /**
   * Transforms GraphQL document by adding __typename fields
   * @param document - GraphQL document to transform
   * @returns Transformed document with __typename fields
   */
  transformDocument(document: DocumentNode): DocumentNode;

  /**
   * Transforms GraphQL document for link usage (inherited from ApolloCache)
   * @param document - GraphQL document to transform
   * @returns Transformed document for network layer
   */
  transformForLink(document: DocumentNode): DocumentNode;

  // DataProxy Methods (inherited from ApolloCache for direct cache access)

  /**
   * Reads a GraphQL query from cache
   * @param options - Query options including query and variables
   * @param optimistic - Whether to include optimistic data (default: false)
   * @returns Query result or null if not found
   */
  readQuery<QueryType, TVariables = any>(
    options: DataProxy.Query<TVariables>, 
    optimistic?: boolean
  ): QueryType | null;

  /**
   * Reads a GraphQL fragment from cache
   * @param options - Fragment options including fragment and id
   * @param optimistic - Whether to include optimistic data (default: false)
   * @returns Fragment result or null if not found
   */
  readFragment<FragmentType, TVariables = any>(
    options: DataProxy.Fragment<TVariables>, 
    optimistic?: boolean
  ): FragmentType | null;

  /**
   * Writes a complete GraphQL query result to cache
   * @param options - Write options including query, data, and variables
   */
  writeQuery<TData = any, TVariables = any>(
    options: Cache.WriteQueryOptions<TData, TVariables>
  ): void;

  /**
   * Writes a GraphQL fragment to cache
   * @param options - Write options including fragment, id, and data
   */
  writeFragment<TData = any, TVariables = any>(
    options: Cache.WriteFragmentOptions<TData, TVariables>
  ): void;

  /**
   * Writes raw data to cache with root query context
   * @param options - Write options including data to write
   */
  writeData<TData = any>(options: Cache.WriteDataOptions<TData>): void;
}

Usage Examples:

import { InMemoryCache } from "apollo-cache-inmemory";
import { gql } from "graphql-tag";

const cache = new InMemoryCache();

// Write data to cache
cache.write({
  query: gql`
    query GetUser($id: ID!) {
      user(id: $id) {
        id
        name
        email
      }
    }
  `,
  variables: { id: "1" },
  result: {
    user: {
      id: "1",
      name: "Alice",
      email: "alice@example.com",
      __typename: "User"
    }
  }
});

// Read data from cache
const result = cache.read({
  query: gql`
    query GetUser($id: ID!) {
      user(id: $id) {
        id
        name
        email
      }
    }
  `,
  variables: { id: "1" }
});

// Watch for changes
const unwatch = cache.watch({
  query: gql`query GetUser($id: ID!) { user(id: $id) { id name } }`,
  variables: { id: "1" },
  callback: (result) => {
    console.log("Cache updated:", result);
  }
});

// Stop watching
unwatch();

// DataProxy methods for direct cache access
// Write query data directly
cache.writeQuery({
  query: gql`
    query GetUser($id: ID!) {
      user(id: $id) { id name email }
    }
  `,
  variables: { id: "2" },
  data: {
    user: {
      id: "2",
      name: "Bob",
      email: "bob@example.com",
      __typename: "User"
    }
  }
});

// Read query data directly
const userData = cache.readQuery({
  query: gql`
    query GetUser($id: ID!) {
      user(id: $id) { id name email }
    }
  `,
  variables: { id: "2" }
});

// Write fragment data
cache.writeFragment({
  id: "User:1",
  fragment: gql`
    fragment UserName on User {
      name
    }
  `,
  data: {
    name: "Alice Updated",
    __typename: "User"
  }
});

// Read fragment data
const userName = cache.readFragment({
  id: "User:1",
  fragment: gql`
    fragment UserName on User {
      name
    }
  `
});

Cache Configuration

Configuration interface for customizing InMemoryCache behavior.

interface InMemoryCacheConfig extends ApolloReducerConfig {
  /**
   * Enable result caching with dependency tracking (default: true)
   * Improves performance for repeated reads but uses more memory
   */
  resultCaching?: boolean;

  /**
   * Freeze result objects to prevent mutation (default: false)
   * Helps catch accidental mutations but impacts performance
   */
  freezeResults?: boolean;
}

interface ApolloReducerConfig {
  /**
   * Function to generate unique IDs for objects during normalization
   * Default uses __typename + id or _id fields
   */
  dataIdFromObject?: IdGetter;

  /**
   * Fragment matcher for handling GraphQL fragments on unions/interfaces
   * Default uses HeuristicFragmentMatcher
   */
  fragmentMatcher?: FragmentMatcherInterface;

  /**
   * Automatically add __typename to queries (default: true)
   * Required for proper normalization and fragment matching
   */
  addTypename?: boolean;

  /**
   * Map of cache redirects for resolving fields from other locations
   * Used for denormalization and computed fields
   */
  cacheRedirects?: CacheResolverMap;

  // Backward compatibility properties (deprecated)
  /**
   * @deprecated Use cacheRedirects instead
   * Maintained for backward compatibility
   */
  customResolvers?: CacheResolverMap;

  /**
   * @deprecated Use cacheRedirects instead  
   * Maintained for backward compatibility
   */
  cacheResolvers?: CacheResolverMap;
}

Default ID Generation Function

Utility function for generating object IDs during normalization.

/**
 * Default function for generating unique IDs from GraphQL objects
 * Uses __typename combined with id or _id field
 * @param result - Object to generate ID for
 * @returns Unique ID string or null if cannot generate
 */
function defaultDataIdFromObject(result: any): string | null;

Usage Example:

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

const cache = new InMemoryCache({
  dataIdFromObject: (object) => {
    // Custom ID generation logic
    if (object.__typename === "User") {
      return `User:${object.email}`;
    }
    // Fall back to default behavior
    return defaultDataIdFromObject(object);
  }
});

Cache State Management

Methods for extracting and restoring cache state for persistence and hydration.

/**
 * Extracts current cache state as serializable object
 * @param optimistic - Include optimistic updates in extraction
 * @returns Normalized cache object suitable for serialization
 */
extract(optimistic?: boolean): NormalizedCacheObject;

/**
 * Restores cache from previously extracted state
 * @param data - Normalized cache data to restore
 * @returns Cache instance for method chaining
 */
restore(data: NormalizedCacheObject): this;

Usage Example:

// Extract cache state for persistence
const cacheState = cache.extract();
localStorage.setItem("apollo-cache", JSON.stringify(cacheState));

// Restore cache state
const savedState = JSON.parse(localStorage.getItem("apollo-cache") || "{}");
cache.restore(savedState);

Types

interface NormalizedCacheObject {
  [dataId: string]: StoreObject | undefined;
}

interface StoreObject {
  __typename?: string;
  [storeFieldKey: string]: StoreValue;
}

type IdGetter = (value: IdGetterObj) => string | null | undefined;

interface IdGetterObj extends Object {
  __typename?: string;
  id?: string;
}

interface FragmentMatcherInterface {
  match(
    idValue: IdValue,
    typeCondition: string,
    context: ReadStoreContext
  ): boolean | 'heuristic';
}

type CacheResolverMap = {
  [typeName: string]: {
    [fieldName: string]: CacheResolver;
  };
};

type CacheResolver = (
  rootValue: any,
  args: { [argName: string]: any },
  context: any
) => any;