Complete set of GraphQL directives for Apollo Federation schema composition, enabling distributed schema architecture with entity relationships, field resolution control, and schema metadata management.
Designates an object type or interface as a federated entity and specifies its key fields for unique identification across subgraphs.
/**
* @key directive for entity identification
* Locations: OBJECT, INTERFACE
* Repeatable: Yes
*/
const KeyDirective: GraphQLDirective;
// Usage: @key(fields: "id")
// Usage: @key(fields: "id", resolvable: false)
// Usage: @key(fields: "id") @key(fields: "email")Usage Examples:
# Single key entity
type User @key(fields: "id") {
id: ID!
name: String!
email: String!
}
# Multiple keys entity
type Product @key(fields: "id") @key(fields: "sku") {
id: ID!
sku: String!
name: String!
}
# Non-resolvable key (value type)
type Currency @key(fields: "code", resolvable: false) {
code: String!
name: String!
symbol: String!
}
# Interface entity
interface Node @key(fields: "id") {
id: ID!
}Indicates that an object or interface definition extends another definition of the same type, used with subgraph libraries that don't support the extend keyword.
/**
* @extends directive for type extensions
* Locations: OBJECT, INTERFACE
* Repeatable: No
*/
const ExtendsDirective: GraphQLDirective;
// Usage: @extendsUsage Example:
# Extending existing entity from another subgraph
type User @extends @key(fields: "id") {
id: ID! @external
favoriteProducts: [Product!]!
}Indicates that a field is defined in another subgraph and is referenced locally for composition purposes with @requires or @provides.
/**
* @external directive for external field references
* Locations: OBJECT, FIELD_DEFINITION
* Repeatable: No
*/
const ExternalDirective: GraphQLDirective;
// Usage: @externalSpecifies that a field resolver depends on the values of other entity fields resolved by other subgraphs.
/**
* @requires directive for field dependencies
* Locations: FIELD_DEFINITION
* Repeatable: No
*/
const RequiresDirective: GraphQLDirective;
// Usage: @requires(fields: "fieldSelection")Specifies a set of entity fields that a subgraph can resolve at a particular schema path, enabling optimization by reducing subgraph communication.
/**
* @provides directive for field provisioning
* Locations: FIELD_DEFINITION
* Repeatable: No
*/
const ProvidesDirective: GraphQLDirective;
// Usage: @provides(fields: "fieldSelection")Usage Examples:
type User @key(fields: "id") {
id: ID!
email: String! @external
name: String! @external
# This field requires email from another subgraph
profileUrl: String! @requires(fields: "email")
}
type Review @key(fields: "id") {
id: ID!
# This field provides author name to avoid extra fetch
author: User! @provides(fields: "name")
rating: Int!
}Indicates that an object type's field can be resolved by multiple subgraphs, overriding Federation 2's default single-subgraph field ownership.
/**
* @shareable directive for multi-subgraph fields
* Locations: FIELD_DEFINITION, OBJECT
* Repeatable: No
*/
const ShareableDirective: GraphQLDirective;
// Usage: @shareableEnables migrating field resolution from one subgraph to another by indicating the source subgraph to override.
/**
* @override directive for field migration
* Locations: FIELD_DEFINITION
* Repeatable: No
*/
const OverrideDirective: GraphQLDirective;
// Usage: @override(from: "sourceSubgraph")
// Usage: @override(from: "sourceSubgraph", label: "migrationLabel")Usage Examples:
# Shareable field across multiple subgraphs
type Product @key(fields: "id") {
id: ID!
name: String! @shareable
description: String!
}
# Override field from another subgraph
type User @key(fields: "id") {
id: ID!
# Moving this field from accounts subgraph
email: String! @override(from: "accounts")
}Applies arbitrary string metadata to schema locations for use by custom tooling, contracts, and documentation systems.
/**
* @tag directive for metadata annotation
* Locations: Multiple (FIELD_DEFINITION, OBJECT, INTERFACE, etc.)
* Repeatable: Yes
*/
const TagDirective: GraphQLDirective;
// Usage: @tag(name: "tagName")Indicates that a definition should be omitted from the router's API schema, even if present in other subgraphs.
/**
* @inaccessible directive for schema filtering
* Locations: Multiple (FIELD_DEFINITION, OBJECT, INTERFACE, etc.)
* Repeatable: No
*/
const InaccessibleDirective: GraphQLDirective;
// Usage: @inaccessibleUsage Examples:
# Tagged for contract filtering
type User @key(fields: "id") @tag(name: "public") {
id: ID!
name: String! @tag(name: "public")
# Internal field not exposed to clients
internalId: String! @inaccessible
# Beta feature tagged for filtering
betaFeature: String @tag(name: "beta")
}Links external specification definitions to the schema, primarily used for federation specification imports.
/**
* @link directive for external specifications
* Locations: SCHEMA
* Repeatable: Yes (implied)
*/
const LinkDirective: GraphQLDirective;
// Usage: @link(url: "specificationUrl")
// Usage: @link(url: "specificationUrl", import: [items])Usage Example:
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key", "@requires", "@provides", "@external"])Complete collection of all federation directives for programmatic access.
/**
* Array containing all federation directives
*/
const federationDirectives: GraphQLDirective[];Utility function to determine if a directive is federation-specific.
/**
* Checks if a directive is a federation directive
* @param directive - GraphQL directive to check
* @returns True if directive is federation-specific
*/
function isFederationDirective(directive: GraphQLDirective): boolean;Usage Example:
import { federationDirectives, isFederationDirective } from "@apollo/subgraph";
// Access all federation directives
federationDirectives.forEach(directive => {
console.log(`Directive: @${directive.name}`);
});
// Check if directive is federation-specific
const customDirective = new GraphQLDirective({
name: 'custom',
locations: [DirectiveLocation.FIELD_DEFINITION]
});
console.log(isFederationDirective(customDirective)); // false
console.log(isFederationDirective(KeyDirective)); // trueExtract all directives from schema elements for analysis and processing.
/**
* Gathers all directives from a schema element
* @param element - Schema element (type, field, etc.)
* @returns Array of directive nodes
*/
function gatherDirectives(
element: GraphQLSchema | GraphQLNamedType | GraphQLField<any, any> |
GraphQLArgument | GraphQLEnumValue | GraphQLInputField
): DirectiveNode[];Check if a specific type includes a particular directive by name.
/**
* Checks if type has a specific directive
* @param type - GraphQL named type
* @param directiveName - Name of directive to check
* @returns True if type has the directive
*/
function typeIncludesDirective(
type: GraphQLNamedType,
directiveName: string
): boolean;Compare directive definitions for compatibility in schema composition.
/**
* Checks if directive definitions are compatible
* @param baseDefinition - Base directive definition
* @param toCompare - Directive definition to compare
* @returns True if definitions are compatible
*/
function directiveDefinitionsAreCompatible(
baseDefinition: DirectiveDefinitionNode,
toCompare: DirectiveDefinitionNode
): boolean;Usage Examples:
import {
gatherDirectives,
typeIncludesDirective,
directiveDefinitionsAreCompatible
} from "@apollo/subgraph";
// Check if type is an entity
const userType = schema.getType('User');
const isEntity = typeIncludesDirective(userType, 'key');
// Gather all directives on a field
const field = userType.getFields()['email'];
const directives = gatherDirectives(field);
// Compare directive compatibility
const compatible = directiveDefinitionsAreCompatible(
baseKeyDirective.astNode,
extendedKeyDirective.astNode
);/**
* AST nodes that can have directives
*/
type ASTNodeWithDirectives =
| FieldDefinitionNode
| InputValueDefinitionNode
| EnumValueDefinitionNode
| ExecutableDefinitionNode
| SchemaDefinitionNode
| TypeDefinitionNode
| TypeSystemExtensionNode;
/**
* @deprecated Use GraphQLNamedType instead
*/
type GraphQLNamedTypeWithDirectives = GraphQLNamedType;# Define entity with key
type Product @key(fields: "id") {
id: ID!
name: String!
}
# Extend entity in another subgraph
type Product @extends @key(fields: "id") {
id: ID! @external
reviews: [Review!]!
}type User @key(fields: "id") {
id: ID!
firstName: String! @external
lastName: String! @external
# Requires both first and last name
fullName: String! @requires(fields: "firstName lastName")
}type Review @key(fields: "id") {
id: ID!
# Provides author name to avoid additional fetch
author: User! @provides(fields: "name")
rating: Int!
}