Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Split @apollo/subgraph package from @apollo/federation #1058

Merged
merged 10 commits into from
Oct 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = {
requirePragma: true,
overrides: [
{
files: '{docs/{,source/**},.,{gateway-js,federation-js,harmonizer,federation-integration-testsuite-js,query-planner-js}/**,test}/{*.js,*.ts}',
files: '{docs/{,source/**},.,{gateway-js,federation-js,harmonizer,federation-integration-testsuite-js,query-planner-js,subgraph-js}/**,test}/{*.js,*.ts}',
options: {
requirePragma: false,
trailingComma: 'all',
Expand Down
1 change: 1 addition & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ There is not a root `CHANGELOG.md` on this monorepo. Instead, there are `CHANGE

- `./federation-js/CHANGELOG.md` for `@apollo/federation`
- `./query-planner-js/CHANGELOG.md` for `@apollo/query-planner`
- `./subgraph-js/CHANGELOG.md` for `@apollo/subgraph`

> Since this is not a direct dependency of our _primary_ consumers, it is best to *also* surface important changes in `@apollo/gateway`'s `CHANGELOG.md`.
- `./gateway-js/CHANGELOG.md` for `@apollo/gateway`.
Expand Down
2 changes: 1 addition & 1 deletion docs/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module.exports = {
'opentelemetry',
],
'Third-Party Support': ['other-servers', 'federation-spec'],
'API Reference': ['api/apollo-federation', 'api/apollo-gateway'],
'API Reference': ['api/apollo-subgraph', 'api/apollo-gateway'],
},
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: "API Reference: @apollo/federation"
sidebar_title: "@apollo/federation"
title: "API Reference: @apollo/subgraph"
sidebar_title: "@apollo/subgraph"
description: Apollo Federation API reference
api_reference: true
---

This API reference documents the exports from the `@apollo/federation` package.
This API reference documents the exports from the `@apollo/subgraph` package.

## `buildSubgraphSchema`
> This method was renamed from `buildFederatedSchema` after @apollo/federation v0.28.0 (the previous name still works but might be removed in a future release).
> This method previously existed in the `@apollo/federation` package and was renamed from `buildFederatedSchema` after @apollo/federation v0.28.0 (the previous name still works but might be removed in a future release).

A function that takes an array of GraphQL schema modules and returns a federation-ready schema based on those modules:

Expand Down
2 changes: 1 addition & 1 deletion docs/source/enterprise-guide/graphql-consolidation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Unlike other distributed GraphQL architectures such as schema stitching, federat

Apollo Server provides open source libraries that allow it to act both as a subgraph and as a gateway, but these components can be implemented in any language and framework. Specifically, Apollo Server supports federation via two open-source extension libraries:

- [`@apollo/federation`](https://www.npmjs.com/package/@apollo/federation) provides primitives that your subgraphs use to make their individual GraphQL schemas composable
- [`@apollo/subgraph`](https://www.npmjs.com/package/@apollo/subgraph) provides primitives that your subgraphs use to make their individual GraphQL schemas composable
- [`@apollo/gateway`](https://www.npmjs.com/package/@apollo/gateway) enables you to set up an instance of Apollo Server as a gateway that distributes incoming GraphQL operations across one or more subgraphs

### Core principles of federation
Expand Down
2 changes: 1 addition & 1 deletion docs/source/entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The gateway provides this representation to the entity's originating subgraph to
}
```

> Reference resolvers are a special addition to Apollo Server that enable entities to be referenced by other subgraphs. They are called whenever a query references an `entity` across subgraph boundaries. To learn more about `__resolveReference`, see the [API docs](/api/apollo-federation/).
> Reference resolvers are a special addition to Apollo Server that enable entities to be referenced by other subgraphs. They are called whenever a query references an `entity` across subgraph boundaries. To learn more about `__resolveReference`, see the [API docs](/api/apollo-subgraph/).

With this model, each implementing subgraph's schema represents a true subset of the complete graph. This prevents the need for defining foreign-key fields in individual schemas, and enables clients to transparently execute a query like the following, which hits both the `products` and `reviews` subgraphs:

Expand Down
4 changes: 2 additions & 2 deletions docs/source/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,8 @@ This mode enables multiple teams working on a graph to coordinate when and how u

Apollo Server supports Apollo Federation via two open-source extension libraries:

* [`@apollo/federation`](./api/apollo-federation/) provides primitives that subgraphs use to make their individual GraphQL schemas composable.
* [`@apollo/gateway`](./api/apollo-gateway) enables you to set up an instance of Apollo Server as a **gateway** that distributes incoming GraphQL operations across one or more subgraphs.
* [`@apollo/subgraph`](./api/apollo-subgraph/) provides primitives that subgraphs use to make their individual GraphQL schemas composable.
* [`@apollo/gateway`](./api/apollo-gateway) enables you to set up an instance of Apollo Server as a **gateway** that distributes incoming GraphQL operations across one or more subgraphs.

---

Expand Down
6 changes: 3 additions & 3 deletions docs/source/migrating-from-stitching.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ Because of this, we recommend that you migrate your subgraphs in-place instead o

### Using Apollo Server

If your subgraphs use Apollo Server, add federation support to them by installing the `@apollo/federation` package:
If your subgraphs use Apollo Server, add federation support to them by installing the `@apollo/subgraph` package:

```bash
npm install @apollo/federation
npm install @apollo/subgraph
```

Then use the `buildSubgraphSchema` function to augment your schema with fields that are necessary for federation support:

```js
const { ApolloServer } = require('apollo-server');
const { buildSubgraphSchema } = require('@apollo/federation');
const { buildSubgraphSchema } = require('@apollo/subgraph');

const server = new ApolloServer({
schema: buildSubgraphSchema([
Expand Down
2 changes: 1 addition & 1 deletion docs/source/performance/caching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Server-side caching
sidebar_title: Caching
---

> Using cache control with Apollo Federation requires v0.28 of `@apollo/federation` in your subgraph, v0.36 of `@apollo/gateway` in your router, and v3.0.2 of Apollo Server in both servers. Please note that Apollo Server's cache hints API has evolved as of v3, so be sure to review the [updated caching documentation](https://www.apollographql.com/docs/apollo-server/performance/caching/).
> Using cache control with Apollo Federation requires v0.1.0 of `@apollo/subgraph` (previously v0.28 of `@apollo/federation`) in your subgraph, v0.36 of `@apollo/gateway` in your router, and v3.0.2 of Apollo Server in both servers. Please note that Apollo Server's cache hints API has evolved as of v3, so be sure to review the [updated caching documentation](https://www.apollographql.com/docs/apollo-server/performance/caching/).

## Using cache hints with subgraphs

Expand Down
8 changes: 4 additions & 4 deletions docs/source/quickstart-pt-3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ A service that you want to act as a subgraph can use any GraphQL server that sup

> If you're using a GraphQL server besides Apollo Server, consult its documentation to learn how to configure it for use as a federated service.

If you have an existing GraphQL API that uses Apollo Server, you can use that server as a subgraph with the `@apollo/federation` library. You can get started with [this example server](https://github.com/apollographql/docs-examples/tree/main/apollo-server/v3/getting-started) (which is not yet federated).
If you have an existing GraphQL API that uses Apollo Server, you can use that server as a subgraph with the `@apollo/subgraph` library. You can get started with [this example server](https://github.com/apollographql/docs-examples/tree/main/apollo-server/v3/getting-started) (which is not yet federated).

First, install the `@apollo/federation` library in your project:
First, install the `@apollo/subgraph` library in your project:

```shell
npm install @apollo/federation
npm install @apollo/subgraph
```

Next, import the `buildSubgraphSchema` function in the file where you initialize `ApolloServer`:

```js:title=index.js
const { buildSubgraphSchema } = require('@apollo/federation');
const { buildSubgraphSchema } = require('@apollo/subgraph');
```

Finally, modify your `ApolloServer` constructor by passing it a `schema` option instead of `typeDefs` and `resolvers`, like so:
Expand Down
12 changes: 6 additions & 6 deletions docs/source/subgraphs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ server.listen(4001).then(({ url }) => {

This should look familiar if you've [set up Apollo Server](https://www.apollographql.com/docs/apollo-server/getting-started/) before. If it doesn't, we recommend you familiarize yourself with the basics before jumping into federation.

Now, let's convert this to a subgraph. The first step is to install the `@apollo/federation` package in our project:
Now, let's convert this to a subgraph. The first step is to install the `@apollo/subgraph` package in our project:

```shell
npm install @apollo/federation
npm install @apollo/subgraph
```

### Defining an entity
Expand All @@ -62,7 +62,7 @@ As part of our federated architecture, we want _other_ subgraphs to be able to e

```js:title=index.js
const { ApolloServer, gql } = require('apollo-server');
const { buildSubgraphSchema } = require('@apollo/federation');
const { buildSubgraphSchema } = require('@apollo/subgraph');

const typeDefs = gql`
type Query {
Expand Down Expand Up @@ -101,7 +101,7 @@ const resolvers = {

### Generating a subgraph schema

Finally, we use the `buildSubgraphSchema` function from the `@apollo/federation` package to augment our schema definition with federation support. We provide the result of this function to the `ApolloServer` constructor:
Finally, we use the `buildSubgraphSchema` function from the `@apollo/subgraph` package to augment our schema definition with federation support. We provide the result of this function to the `ApolloServer` constructor:

```js:title=index.js
const server = new ApolloServer({
Expand All @@ -121,7 +121,7 @@ Here are the snippets above combined (again, note that for this sample to be com

```js:title=index.js
const { ApolloServer, gql } = require('apollo-server');
const { buildSubgraphSchema } = require('@apollo/federation');
const { buildSubgraphSchema } = require('@apollo/subgraph');

const typeDefs = gql`
type Query {
Expand Down Expand Up @@ -279,7 +279,7 @@ const server = new ApolloServer({

```js
const { ApolloServer, gql, SchemaDirectiveVisitor } = require('apollo-server');
const { buildSubgraphSchema } = require ('@apollo/federation')
const { buildSubgraphSchema } = require ('@apollo/subgraph')

// typeDefs and resolvers defined here

Expand Down
1 change: 1 addition & 0 deletions docs/static/_redirects
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/implementing-services/ /docs/federation/subgraphs/
/managed-federation/advanced-topics/ /docs/federation/managed-federation/overview/
/managed-federation/monitoring/ /docs/federation/performance/monitoring
/docs/federation/api/apollo-federation/ /docs/federation/api/apollo-subgraph/
39 changes: 1 addition & 38 deletions federation-js/README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,3 @@
# `Apollo Federation Utilities`

This package provides utilities for creating GraphQL microservices, which can be combined into a single endpoint through tools like [Apollo Gateway](https://github.com/apollographql/apollo-server/tree/main/packages/apollo-gateway).

For complete documentation, see the [Apollo Federation API reference](https://www.apollographql.com/docs/apollo-server/api/apollo-federation/).

## Usage

```js
const { ApolloServer, gql } = require("apollo-server");
const { buildSubgraphSchema } = require("@apollo/federation");

const typeDefs = gql`
type Query {
me: User
}

type User @key(fields: "id") {
id: ID!
username: String
}
`;

const resolvers = {
Query: {
me() {
return { id: "1", username: "@ava" }
}
},
User: {
__resolveReference(user, { fetchUserById }){
return fetchUserById(user.id)
}
}
};

const server = new ApolloServer({
schema: buildSubgraphSchema([{ typeDefs, resolvers }])
});
```
**Note:** If you have arrived here, you are probably looking for the [`@apollo/subgraph`](https://npm.im/@apollo/subgraph) package, which provides the `buildSubgraphSchema` function for subgraph authors. This package now only contains code for composing subgraphs, which is primarily a gateway and tooling concern.
1 change: 1 addition & 0 deletions federation-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"access": "public"
},
"dependencies": {
"@apollo/subgraph": "file:../subgraph-js",
"apollo-graphql": "^0.9.3",
"apollo-server-types": "^3.0.2",
"lodash.xorby": "^4.7.0"
Expand Down
6 changes: 5 additions & 1 deletion federation-js/src/composition/DirectiveMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import {
VisitFn,
} from 'graphql';
import { mapGetOrSet } from '../utilities';
import { FederationField, FederationType, ServiceDefinition } from './types';
import { ServiceDefinition } from './types';
import type {
FederationField,
FederationType,
} from '@apollo/subgraph/dist/schemaExtensions';
import { getFederationMetadata } from './utils';

// directive name => usages
Expand Down
20 changes: 11 additions & 9 deletions federation-js/src/composition/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import {
} from 'graphql';
import { transformSchema } from 'apollo-graphql';
import {
otherKnownDirectiveDefinitions,
otherKnownDirectives,
federationDirectives,
} from '../directives';
isFederationDirective,
} from '@apollo/subgraph/dist/directives';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable to depend on these in this direction right now. Just might be one of those things that doesn't find the perfect home until after @pcmanus finishes working on breaking out some other packages (for composition)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, presumably most or all of this stuff disappears in the future!

import {
findDirectivesOnNode,
isStringValueNode,
Expand All @@ -36,17 +37,18 @@ import {
getFederationMetadata,
CompositionResult,
isDirectiveDefinitionNode,
isFederationDirective,
parseFieldSet,
} from './utils';
import {
ServiceDefinition,
ExternalFieldDefinition,
ServiceNameToKeyDirectivesMap,
FederationType,
FederationField,
FederationDirective,
} from './types';
import type {
FederationField,
FederationType,
ServiceNameToKeyDirectivesMap,
} from '@apollo/subgraph/dist/schemaExtensions';
trevor-scheer marked this conversation as resolved.
Show resolved Hide resolved
import { validateSDL } from 'graphql/validation/validate';
import { compositionRules } from './rules';
import { printSupergraphSdl } from '../service/printSupergraphSdl';
Expand Down Expand Up @@ -361,8 +363,8 @@ export function buildSchemaFromDefinitionsAndExtensions({

// We only want to include the definitions of other known Apollo directives
// (currently just @tag) if there are usages.
const otherKnownDirectiveDefinitionsToInclude =
otherKnownDirectiveDefinitions.filter((directive) =>
const otherKnownDirectivesToInclude =
otherKnownDirectives.filter((directive) =>
directiveMetadata.hasUsages(directive.name),
);

Expand All @@ -385,7 +387,7 @@ export function buildSchemaFromDefinitionsAndExtensions({
JoinGraphDirective,
...specifiedDirectives,
...federationDirectives,
...otherKnownDirectiveDefinitionsToInclude,
...otherKnownDirectivesToInclude,
],
types: [FieldSetScalar, JoinGraphEnum],
});
Expand Down
4 changes: 2 additions & 2 deletions federation-js/src/composition/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
reservedRootFields,
defaultRootOperationNameLookup
} from './utils';
import apolloTypeSystemDirectives from '../directives';
import { knownSubgraphDirectives } from '@apollo/subgraph/dist/directives';

export function normalizeTypeDefs(typeDefs: DocumentNode) {
// The order of this is important - `stripCommonPrimitives` must come after
Expand Down Expand Up @@ -299,7 +299,7 @@ export function stripCommonPrimitives(document: DocumentNode) {
// Remove all common directive definitions from the document
DirectiveDefinition(node) {
const isCommonDirective = [
...apolloTypeSystemDirectives,
...knownSubgraphDirectives,
...specifiedDirectives,
].some((directive) => directive.name === node.name.value);
return isCommonDirective ? null : node;
Expand Down
30 changes: 0 additions & 30 deletions federation-js/src/composition/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import {
DocumentNode,
FieldDefinitionNode,
DirectiveDefinitionNode,
FieldNode,
InlineFragmentNode,
} from 'graphql';
import { DirectiveUsages } from './DirectiveMetadata';

export type Maybe<T> = null | undefined | T;

Expand All @@ -22,33 +19,6 @@ export interface ExternalFieldDefinition {
serviceName: string;
}

export interface ServiceNameToKeyDirectivesMap {
[serviceName: string]: FieldSet[] | undefined;
}

export interface FederationType {
serviceName?: ServiceName;
keys?: ServiceNameToKeyDirectivesMap;
externals?: {
[serviceName: string]: ExternalFieldDefinition[];
};
isValueType?: boolean;
directiveUsages?: DirectiveUsages
}

// Without rewriting a number of AST types from graphql-js, this typing is
// technically too relaxed. Recursive selections are not excluded from containing
// FragmentSpreads, which is what this type is aiming to achieve (and accomplishes
// at the root level, but not recursively)
export type FieldSet = readonly (FieldNode | InlineFragmentNode)[];
export interface FederationField {
serviceName?: ServiceName;
requires?: FieldSet;
provides?: FieldSet;
belongsToValueType?: boolean;
directiveUsages?: DirectiveUsages
}

export interface FederationDirective {
directiveDefinitions: {
[serviceName: string]: DirectiveDefinitionNode;
Expand Down
Loading