or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

federation-directives.mdfederation-types.mdindex.mdschema-building.mdschema-printing.md
tile.json

schema-building.mddocs/

Schema Building

Core functionality for transforming regular GraphQL schemas into federation-aware subgraph schemas with automatic entity resolution, service introspection, and federation directive processing.

Capabilities

Build Subgraph Schema

Transforms regular GraphQL schemas into federation-aware subgraph schemas by adding entity resolution, service introspection, and processing federation directives.

/**
 * Transforms regular GraphQL schemas into federation-aware subgraph schemas
 * @param modulesOrSDL - Schema modules, documents, or legacy format
 * @returns Federation-aware GraphQL schema
 */
function buildSubgraphSchema(
  modulesOrSDL: (GraphQLSchemaModule | DocumentNode)[] | DocumentNode | LegacySchemaModule
): GraphQLSchema;

interface GraphQLSchemaModule {
  /** GraphQL type definitions as AST */
  typeDefs: DocumentNode;
  /** Optional resolver map for the type definitions */
  resolvers?: GraphQLResolverMap<any>;
}

interface LegacySchemaModule {
  /** Type definitions - single document or array */
  typeDefs: DocumentNode | DocumentNode[];
  /** Optional resolver map */
  resolvers?: GraphQLResolverMap<unknown>;
}

Usage Examples:

import { buildSubgraphSchema } from "@apollo/subgraph";
import { gql } from "graphql-tag";

// Single module approach
const schema = buildSubgraphSchema({
  typeDefs: gql`
    type Query {
      product(id: ID!): Product
    }

    type Product @key(fields: "id") {
      id: ID!
      name: String!
      price: Float
    }
  `,
  resolvers: {
    Query: {
      product: (_, { id }) => ({ id, name: "Sample Product", price: 29.99 })
    },
    Product: {
      __resolveReference: (product) => ({ ...product, name: "Resolved Product" })
    }
  }
});

// Multiple modules approach
const schema = buildSubgraphSchema([
  {
    typeDefs: gql`
      type Query {
        me: User
      }
    `,
    resolvers: {
      Query: {
        me: () => ({ id: "1", email: "user@example.com" })
      }
    }
  },
  {
    typeDefs: gql`
      type User @key(fields: "id") {
        id: ID!
        email: String!
      }
    `,
    resolvers: {
      User: {
        __resolveReference: (user) => ({ ...user, email: "resolved@example.com" })
      }
    }
  }
]);

// Raw SDL approach
const schema = buildSubgraphSchema(gql`
  type Query {
    hello: String
  }
`);

Legacy Build Function

Deprecated function maintained for backward compatibility.

/**
 * @deprecated Use buildSubgraphSchema instead
 */
const buildFederatedSchema: typeof buildSubgraphSchema;

Additional Documentation

Note: The @apollo/subgraph package exports only buildSubgraphSchema and printSubgraphSchema. The schema building process uses internal utilities for validation, module processing, and schema transformation, but these are not part of the public API.

Federation Integration

Automatic Entity Resolution

The buildSubgraphSchema function automatically:

  1. Identifies Entities: Types with @key directive become federated entities
  2. Adds _entities Resolver: Handles entity resolution from representations
  3. Adds _service Field: Provides SDL introspection for the gateway
  4. Processes __resolveReference: Custom entity resolution logic
  5. Handles __typename: Automatic type identification for entities

Resolver Map Structure

Federation-specific resolver patterns:

const resolvers = {
  // Regular field resolvers
  Query: {
    product: (parent, args, context, info) => { /* ... */ }
  },
  
  // Entity reference resolver
  Product: {
    __resolveReference: (representation, context, info) => {
      // Resolve entity from minimal representation
      return fetchProduct(representation.id);
    }
  },
  
  // Interface/Union type resolver
  Node: {
    __resolveType: (obj, context, info) => {
      return obj.__typename;
    }
  }
};

Type Utilities

Type Guards

/**
 * Type guard for AST nodes
 */
function isNode(maybeNode: any): maybeNode is ASTNode;

/**
 * Type guard for DocumentNode
 */
function isDocumentNode(node: ASTNode): node is DocumentNode;