Skip to content

Commit

Permalink
Merge branch 'main' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
clenfest committed Jun 5, 2024
2 parents cd071d4 + 19746ad commit 868c73c
Show file tree
Hide file tree
Showing 36 changed files with 454 additions and 80 deletions.
4 changes: 3 additions & 1 deletion docs/source/building-supergraphs/jetbrains-ide-support.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
title: Federation support in JetBrains IDEs
title: Federation Support in JetBrains IDEs
subtitle: Streamline federated GraphQL development
description: Enhance your development workflow with federation-specific features in IntelliJ-based IDEs using the GraphQL Plugin.
---

The [GraphQL Plugin for JetBrains](https://plugins.jetbrains.com/plugin/8097-graphql/) provides federation-specific development features, such as auto-complete for federation directives. However, you must enable this federation support after installing the plugin. Otherwise, your IDE might display unexpected errors while you're working with a subgraph schema.
Expand Down
7 changes: 4 additions & 3 deletions docs/source/building-supergraphs/router.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: The router
description: The entry point to your supergraph
title: The Router
subtitle: Learn about the entry point to your federated GraphQL API
description: Learn how to configure a router to act as the gateway to your subgraphs, facilitating seamless execution of operations across multiple services. Efficiently manage and orchestrate your federated supergraph with a robust router setup.
---

After you set up at least one federation-ready [subgraph](./subgraphs-overview/), you can configure a router to sit in front of your subgraphs. The router serves as the entry point to your supergraph, and it executes incoming operations across one or more of your subgraphs:
Expand All @@ -25,7 +26,7 @@ Apollo actively supports the following options for your router:
- **The Apollo Router (recommended)**: This is a high-performance, precompiled Rust binary.

- If you're getting started with federation, we recommend [creating a cloud supergraph](/graphos/quickstart/cloud/) with Apollo GraphOS. With a cloud supergraph, GraphOS provisions and manages your router for you.
- You can also host your own Apollo Router instances. [See the federation quickstart](../quickstart/setup/) to get started.
- You can also host your own Apollo Router instances. [See the Federation Quickstart](../quickstart/setup/) to get started.

- **Apollo Server**: Apollo Server can act as your router via the [`@apollo/gateway`](https://www.npmjs.com/package/@apollo/gateway) extension library.
- [See how to set up Apollo Gateway](/apollo-server/using-federation/apollo-gateway-setup).
Expand Down
5 changes: 3 additions & 2 deletions docs/source/building-supergraphs/subgraphs-overview.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Subgraphs
description: In a federated supergraph
subtitle: Learn about subgraphs in a federated supergraph
description: Understand the concept of subgraphs, explore library options, and learn how to secure and optimize your subgraphs for efficient supergraph operations.
---

Every federated supergraph includes one or more _subgraphs_. Each subgraph is a separate GraphQL service that's responsible for a different portion of your supergraph's available data.
Expand All @@ -20,7 +21,7 @@ flowchart LR;
class clients secondary;
```

You can implement different subgraphs using completely different programming languages and GraphQL server libraries!
You can implement different subgraphs using completely different programming languages and GraphQL server libraries.

## Choosing a subgraph library

Expand Down
5 changes: 3 additions & 2 deletions docs/source/building-supergraphs/supported-subgraphs.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Federation-compatible subgraph implementations
description: For use in a federated supergraph
title: Federation-Compatible Subgraph Implementations
subtitle: Reference for compatible GraphQL server libraries
description: Reference for open-source GraphQL server libraries and hosted solutions that are compatible with Apollo Federation.
---

The following open-source GraphQL server libraries and hosted solutions support acting as a subgraph in a federated supergraph. Their support is tracked in Apollo's [subgraph compatibility repository](https://github.com/apollographql/apollo-federation-subgraph-compatibility). Check out the repository for details on the compatibility tests listed in the table below.
Expand Down
46 changes: 23 additions & 23 deletions docs/source/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,57 @@
"Introduction": "/",
"Changelog": "/federation-versions",
"Quickstart": {
"Project setup": "/quickstart/setup",
"Project Setup": "/quickstart/setup",
"Composition in GraphOS Studio": "/quickstart/studio-composition",
"Local composition": "/quickstart/local-composition",
"Working with subgraphs": "/quickstart/local-subgraphs"
"Local Composition": "/quickstart/local-composition",
"Working with Subgraphs": "/quickstart/local-subgraphs"
},
"Building Your Supergraph": {
"Subgraphs": "/building-supergraphs/subgraphs-overview",
"Supported subgraph libraries": "/building-supergraphs/supported-subgraphs",
"Router / Gateway": "/building-supergraphs/router",
"Apollo Server subgraphs": "https://apollographql.com/docs/apollo-server/using-federation/apollo-subgraph-setup",
"Supported Subgraph Libraries": "/building-supergraphs/supported-subgraphs",
"Router": "/building-supergraphs/router",
"Apollo Server Subgraphs": "https://apollographql.com/docs/apollo-server/using-federation/apollo-subgraph-setup",
"JetBrains IDE Support": "/building-supergraphs/jetbrains-ide-support"
},
"Federated Schemas": {
"Overview": "/federated-types/overview",
"Composition": "/federated-types/composition",
"Federated directives": "/federated-types/federated-directives",
"Sharing types (value types)": "/federated-types/sharing-types",
"Introduction to entities": "/entities",
"Advanced entities": "/entities-advanced",
"Entity interfaces": "/federated-types/interfaces",
"Migrating from schema stitching": "/migrating-from-stitching"
"Federated Directives": "/federated-types/federated-directives",
"Sharing Types (Value Types)": "/federated-types/sharing-types",
"Introduction to Entities": "/entities",
"Advanced Entities": "/entities-advanced",
"Entity Interfaces": "/federated-types/interfaces",
"Migrating from Schema Stitching": "/migrating-from-stitching"
},
"Managed Federation": {
"Overview": "/managed-federation/overview",
"Setup": "/managed-federation/setup",
"Uplink": "/managed-federation/uplink",
"Federated schema checks": "/managed-federation/federated-schema-checks",
"Deployment best practices": "/managed-federation/deployment",
"Opt-in error reporting": "/managed-federation/error-reporting",
"Studio features": "https://www.apollographql.com/docs/graphos/graphs/federated-graphs"
"Federated Schema Checks": "/managed-federation/federated-schema-checks",
"Deployment Best Practices": "/managed-federation/deployment",
"Opt-In Error Reporting": "/managed-federation/error-reporting",
"Studio Features": "https://www.apollographql.com/docs/graphos/graphs/federated-graphs"
},
"Performance": {
"Caching": "/performance/caching",
"Monitoring": "/performance/monitoring",
"Query plans": "/query-plans"
"Query Plans": "/query-plans"
},
"Debugging & Metrics": {
"Error codes": "/errors",
"Composition hints": "/hints",
"Federated trace data": "/metrics",
"Error Codes": "/errors",
"Composition Hints": "/hints",
"Federated Trace Data": "/metrics",
"OpenTelemetry": "/opentelemetry"
},
"API Reference": {
"Subgraph specification": "/subgraph-spec",
"Subgraph Specification": "/subgraph-spec",
"@apollo/subgraph": "https://apollographql.com/docs/apollo-server/using-federation/api/apollo-subgraph",
"@apollo/gateway": "https://apollographql.com/docs/apollo-server/using-federation/api/apollo-gateway"
},
"Moving from Federation 1": {
"Changes from Federation 1": "/federation-2/new-in-federation-2",
"Steps to move": "/federation-2/moving-to-federation-2",
"Backward compatibility": "/federation-2/backward-compatibility"
"Steps to Move": "/federation-2/moving-to-federation-2",
"Backward Compatibility": "/federation-2/backward-compatibility"
}
}
}
188 changes: 187 additions & 1 deletion docs/source/entities-advanced.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
title: Advanced topics on federated entities
title: Advanced Topics on Federated Entities
subtitle: Learn about advanced use cases for entities
description: Explore advanced use cases for entities in a federated GraphQL architecture, including compound keys, migrating entity fields, and contributing computed fields.
---

import ProgressiveOverrideEnterprise from '../shared/progressive-override-enterprise.mdx';
Expand Down Expand Up @@ -909,3 +911,187 @@ const resolvers = {
A basic implementation of the `fetchProductByID` function might make a database call each time it's called. If we need to resolve `Product.price` for `N` different products, this results in `N` database calls. These calls are made in addition to the call made by the Reviews subgraph to fetch the initial list of reviews (and the `id` of each product). This is where the "N+1" problem gets its name. If not prevented, this problem can cause performance problems or even enable denial-of-service attacks.

This problem is not limited to reference resolvers. In fact, it can occur with any resolver that fetches from a data store. To handle this problem, we strongly recommend using [the dataloader pattern](https://github.com/graphql/dataloader). Nearly every GraphQL server library provides a dataloader implementation, and you should use it in every resolver. This is true even for resolvers that aren't for entities and that don't return a list. These resolvers can still cause N+1 issues via [batched requests](/technotes/TN0021-graph-security/#batched-requests).

<MinVersion version="2.8">

## Using contexts to share data along type hierarchies

</MinVersion>

Use the `@context` and `@fromContext` directives to set and get a _context_ to share data between types in a subgraph. Contexts provide a way for a subgraph to share data between types of a nested-type hierarchy without overloading entity keys with extraneous fields. Contexts also preserve the separation of concerns between different subgraphs.

In an entity, a nested object may have a dependency on an ancestor type and thus need access to that ancestor's field(s).

To enable a descendant to access an ancestor's field, you could add it as a `@key` field to every entity along the chain of nested types, but that can become problematic. Deeply nested types can change the `@key` fields of many entities. The added field may be irrelevant to the entities it's added to. Most importantly, overloading `@key` fields often breaks the separation of concerns between different subgraphs.

The `@context` and `@fromContext` directives enable a subgraph to share fields without overloading `@key` fields. You can use these directives to define one or more contexts in a subgraph.

### Using one context

As an example of a single context, the subgraph below tracks the last financial transaction made per user. The `Transaction` type is a child of the `User` type. Each transaction depends on the associated user's currency to calculate the transaction amount in the user's currency. That dependency—the `currencyCode` argument of a `Transaction` depending on the `userCurrency { isoCode } ` of a `User`— is defined with a context. The `@context` directive on `User` sets the context, and `@fromContext` on `currencyCode` gets the contextual data.

```graphql title="Example: using @context and @fromContext"
scalar CurrencyCode;

type Currency {
id: ID!
isoCode: CurrencyCode!
}

type User @key(fields: "id") @context(name: "userContext") {
id: ID!
lastTransaction: Transaction!
userCurrency: Currency!
}

type Transaction @key(fields: "id") {
id: ID!
currency: Currency!
amount: Int!
amountInUserCurrency(
currencyCode: CurrencyCode
@fromContext(field: "$userContext { userCurrency { isoCode } }")
): Int!
}
```

<Note>

An argument of `@fromContext` doesn't appear in the API schema. Instead, it's populated automatically by the router.

In the example above, the argument `currencyCode: CurrencyCode!` wouldn't appear in the API schema.

</Note>

### Using multiple contexts

As an example using multiple contexts, the subgraph below has three entities using two contexts and a nested child entity referencing fields using those contexts:

```graphql title="Example: using multiple contexts"
type Query {
a: A!
b: B!
c: C!
}

type A @key(fields: "id") @context(name: "context_1") @context(name: "context_2") {
id: ID!
field: String!
child: Child!
}

type B @key(fields: "id") @context(name: "context_1") @context(name: "context_2") {
id: ID!
field: String!
child: Child!
}

type C @key(fields: "id") @context(name: "context_1") {
id: ID!
anotherField: String!
child: Child!
}

type Child @key(fields: "id") {
id: ID!
prop1(
arg: String! @fromContext(field: "$context_1 { field }")
): Int!
prop2(
arg: String!
@fromContext(field: "$context_2 ... A { field } ... B { field } ... C { anotherField }")
): Int!
}
```

When the same contextual value is set in multiple placesas in the example with the `Child.prop1` and `Child.prop2` `args`—the `FieldValue` must resolve all types from each place into a single value that matches the parameter type.

<Note>

Federation doesn't guarantee which context will be used if a field is reachable via multiple contexts.

</Note>

### Disambiguating contexts

When multiple ancestor entities in the type hierarchy could fulfill a set context, the nearest ancestor is chosen. For example, if both the parent and grandparent of a type can provide the value of a context, the parent is chosen because it's the closer ancestor.

In the following example, given nested types `A`, `B`, and `C`, with `C` referencing a context that either `A` or `B` could provide, `C` uses the value from `B` because it's a closer ancestor to `C` than `A`:

```graphql
type Query {
a: A!
}

type A @key(fields: "id") @context(name: "context_1") {
id: ID!
field: String!
b: B!
}

type B @key(fields: "id") @context(name: "context_1") {
id: ID!
field: String!
c: C!
}

type C @key(fields: "id") {
id: ID!
prop(
arg: String! @fromContext(field: "$context_1 { field }")
): Int!
}
```

In a more complex graph, a field could be reachable via multiple paths, and a different field could be used to resolve the `prop` depending on which path was used.

### Referencing fields across subgraphs

The definition of context scopes can only exist in one subgraph schema. The `@fromContext` directive can't reference a `@context` defined in another subgraph. However, you can use contexts to share data across subgraphs using the `@external` reference.

Reusing the [`Transaction` example](#using-one-context), imagine a subgraph responsible for the `User` and `Currency` types:

```graphql
scalar CurrencyCode

type Currency @shareable {
id: ID!
isoCode: CurrencyCode!
}

type User @key(fields: "id") {
id: ID!
userCurrency: Currency!
}
```

If you want to reference those fields from another subgraph, you can use the `@external` directive to pass data across subgraph boundaries:

```graphql
scalar CurrencyCode

type Currency @shareable {
id: ID!
isoCode: CurrencyCode!
}

type User @key(fields: "id") @context(name: "userContext") {
id: ID!

# This is a reference to the field resolved elsewhere
userCurrency: Currency! @external

# We add this field to our type here
lastTransaction: Transaction!
}

type Transaction @key(fields: "id") {
id: ID!
currency: Currency!
amount: Int!
amountInUserCurrency(
currencyCode: CurrencyCode
@fromContext(field: "$userContext { userCurrency { isoCode } }")
): Int!
}
```
3 changes: 2 additions & 1 deletion docs/source/entities.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Entities in Apollo Federation
description: Resolve types across multiple subgraphs
subtitle: Learn how to resolve federated types across multiple subgraphs
description: Learn to define, contribute to, and reference object types that resolve their fields across multiple subgraphs in a federated GraphQL architecture.
---

<Note>
Expand Down
5 changes: 3 additions & 2 deletions docs/source/errors.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Federation error codes
description: Learn the error codes you can receive if composition fails.
title: Apollo Federation Error Codes
subtitle: Reference for composition error codes
description: Reference the error codes encountered during Apollo Federation schema composition, identifying root causes and solutions for GraphQL debugging.
toc: false
---

Expand Down
5 changes: 3 additions & 2 deletions docs/source/federated-types/composition.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Schema composition
description: In Apollo Federation
title: Schema Composition
subtitle: Learn how subgraph schemas combine into a supergraph schema
description: Learn about schema composition in a federated GraphQL architecture. Explore strategies for handling conflicting types and directives.
---

In Apollo Federation, _composition_ is the process of combining a set of [subgraph schemas](./overview/#subgraph-schemas) into a [supergraph schema](./overview/#supergraph-schema):
Expand Down
Loading

0 comments on commit 868c73c

Please sign in to comment.