Skip to content

Commit 479a7a9

Browse files
Merge pull request #1096 from lennyburdette/schema-directives
fix(subgraph): support `@contact` directive in `printSubgraphSchema`
1 parent 34a54a4 commit 479a7a9

File tree

15 files changed

+213
-99
lines changed

15 files changed

+213
-99
lines changed

federation-integration-testsuite-js/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
},
1919
"homepage": "https://github.com/apollographql/federation#readme",
2020
"dependencies": {
21-
"apollo-graphql": "^0.9.3",
21+
"apollo-graphql": "^0.9.5",
2222
"graphql-tag": "^2.10.4"
2323
}
2424
}

federation-integration-testsuite-js/src/fixtures/books.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@ export const url = `https://${name}.api.com`;
66
export const typeDefs = gql`
77
directive @stream on FIELD
88
directive @transform(from: String!) on FIELD
9+
directive @contact(
10+
name: String!
11+
url: String
12+
description: String
13+
) on SCHEMA
14+
15+
schema
16+
@contact(
17+
name: "books-team"
18+
url: "mailto:[email protected]"
19+
description: "books"
20+
) {
21+
query: Query
22+
}
923
1024
enum CacheControlScope {
1125
PUBLIC
@@ -18,7 +32,6 @@ export const typeDefs = gql`
1832
inheritMaxAge: Boolean
1933
) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
2034
21-
2235
extend type Query {
2336
book(isbn: String!): Book
2437
books: [Book]

federation-js/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
},
2525
"dependencies": {
2626
"@apollo/subgraph": "file:../subgraph-js",
27-
"apollo-graphql": "^0.9.3",
27+
"apollo-graphql": "^0.9.5",
2828
"apollo-server-types": "^3.0.2",
2929
"lodash.xorby": "^4.7.0"
3030
},

federation-js/src/composition/compose.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import {
2121
} from 'graphql';
2222
import { transformSchema } from 'apollo-graphql';
2323
import {
24-
otherKnownDirectives,
25-
federationDirectives,
26-
isFederationDirective,
24+
directivesWithNoDefinitionNeeded,
25+
isDirectiveWithNoDefinitionNeeded,
26+
directivesWithAutoIncludedDefinitions,
2727
} from '@apollo/subgraph/dist/directives';
2828
import {
2929
findDirectivesOnNode,
@@ -361,10 +361,10 @@ export function buildSchemaFromDefinitionsAndExtensions({
361361
}) {
362362
let errors: GraphQLError[] | undefined = undefined;
363363

364-
// We only want to include the definitions of other known Apollo directives
365-
// (currently just @tag) if there are usages.
366-
const otherKnownDirectivesToInclude =
367-
otherKnownDirectives.filter((directive) =>
364+
// We only want to include the definitions of auto-included Apollo directives
365+
// (just @tag) if there are usages.
366+
const autoIncludedDirectiveDefinitions =
367+
directivesWithAutoIncludedDefinitions.filter((directive) =>
368368
directiveMetadata.hasUsages(directive.name),
369369
);
370370

@@ -386,8 +386,8 @@ export function buildSchemaFromDefinitionsAndExtensions({
386386
JoinOwnerDirective,
387387
JoinGraphDirective,
388388
...specifiedDirectives,
389-
...federationDirectives,
390-
...otherKnownDirectivesToInclude,
389+
...directivesWithNoDefinitionNeeded,
390+
...autoIncludedDirectiveDefinitions,
391391
],
392392
types: [FieldSetScalar, JoinGraphEnum],
393393
});
@@ -468,7 +468,9 @@ export function buildSchemaFromDefinitionsAndExtensions({
468468
schema = new GraphQLSchema({
469469
...schema.toConfig(),
470470
directives: [
471-
...schema.getDirectives().filter((x) => !isFederationDirective(x)),
471+
...schema
472+
.getDirectives()
473+
.filter((x) => !isDirectiveWithNoDefinitionNeeded(x)),
472474
],
473475
});
474476

federation-js/src/composition/validate/preNormalization/tagDirective.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
federationDirectives,
2+
directivesWithNoDefinitionNeeded,
33
directiveDefinitionsAreCompatible,
44
} from '@apollo/subgraph/dist/directives';
55
import {
@@ -18,7 +18,7 @@ import { errorWithCode, logDirective } from '../../utils';
1818
// Likely brittle but also will be very obvious if this breaks. Based on the
1919
// content of the error message itself to remove expected errors related to
2020
// omitted federation directives.
21-
const errorsMessagesToFilter = federationDirectives.map(
21+
const errorsMessagesToFilter = directivesWithNoDefinitionNeeded.map(
2222
(directive) => `Unknown directive "@${directive.name}".`,
2323
);
2424
/**

federation-js/src/service/printSupergraphSdl.ts

+24-14
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import type {
3838
import { Maybe } from '../composition';
3939
import { assert } from '../utilities';
4040
import { printFieldSet } from '../composition/utils';
41-
import { otherKnownDirectives } from '@apollo/subgraph/dist/directives';
41+
4242
interface PrintingContext {
4343
// Apollo addition: we need access to a map from serviceName to its corresponding
4444
// sanitized / uniquified enum value `Name` from the `join__Graph` enum
@@ -128,24 +128,34 @@ function printSchemaDefinition(schema: GraphQLSchema): string {
128128
);
129129
}
130130

131+
type CoreDirectiveMap = Record<
132+
string,
133+
{ feature: string; purpose?: 'EXECUTION' }
134+
>;
135+
136+
const alwaysIncludedCoreDirectives: CoreDirectiveMap = {
137+
core: { feature: 'https://specs.apollo.dev/core/v0.2' },
138+
join: { feature: 'https://specs.apollo.dev/join/v0.1', purpose: 'EXECUTION' },
139+
};
140+
141+
const supportedCoreDirectives: CoreDirectiveMap = {
142+
tag: { feature: 'https://specs.apollo.dev/tag/v0.1' },
143+
};
144+
131145
function printCoreDirectives(schema: GraphQLSchema) {
132-
const otherKnownDirectiveNames = otherKnownDirectives.map(
133-
({ name }) => name,
134-
);
146+
const supportedCoreDirectiveNames = Object.keys(supportedCoreDirectives);
135147
const schemaDirectiveNames = schema.getDirectives().map(({ name }) => name);
136-
const otherKnownDirectivesToInclude = schemaDirectiveNames.filter((name) =>
137-
otherKnownDirectiveNames.includes(name),
138-
);
139-
const otherKnownDirectiveSpecUrls = otherKnownDirectivesToInclude.map(
140-
(name) => ({
141-
feature: `https://specs.apollo.dev/${name}/v0.1`,
142-
}),
148+
const supportedCoreDirectiveNamesToInclude = schemaDirectiveNames.filter((name) =>
149+
supportedCoreDirectiveNames.includes(name),
143150
);
151+
const supportedCoreDirectivesToInclude =
152+
supportedCoreDirectiveNamesToInclude.map(
153+
(name) => supportedCoreDirectives[name],
154+
);
144155

145156
return [
146-
{ feature: 'https://specs.apollo.dev/core/v0.2' },
147-
{ feature: 'https://specs.apollo.dev/join/v0.1', purpose: 'EXECUTION' },
148-
...otherKnownDirectiveSpecUrls,
157+
...Object.values(alwaysIncludedCoreDirectives),
158+
...supportedCoreDirectivesToInclude,
149159
].map(
150160
({ feature, purpose }) =>
151161
`\n @core(feature: ${printStringLiteral(feature)}${

gateway-js/CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
> The changes noted within this `vNEXT` section have not been released yet. New PRs and commits which introduce changes should include an entry in this `vNEXT` section as part of their development. When a release is being prepared, a new header will be (manually) created below and the appropriate changes within that release will be moved into the new section.
66
7-
- _Nothing yet. Stay tuned._
7+
- Print `@contact` directive in `printSubgraphSchema` [PR #1096](https://github.com/apollographql/federation/pull/1096)
88

99
## v0.44.0
1010

gateway-js/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"@apollo/query-planner": "file:../query-planner-js",
3131
"@opentelemetry/api": "^1.0.1",
3232
"@types/node-fetch": "2.5.12",
33-
"apollo-graphql": "^0.9.3",
33+
"apollo-graphql": "^0.9.5",
3434
"apollo-reporting-protobuf": "^0.8.0 || ^3.0.0",
3535
"apollo-server-caching": "^0.7.0 || ^3.0.0",
3636
"apollo-server-core": "^2.23.0 || ^3.0.0",

package-lock.json

+16-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

query-planner-js/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"access": "public"
2626
},
2727
"dependencies": {
28-
"apollo-graphql": "^0.9.3",
28+
"apollo-graphql": "^0.9.5",
2929
"chalk": "^4.1.0",
3030
"deep-equal": "^2.0.5",
3131
"pretty-format": "^26.0.0"

subgraph-js/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"access": "public"
2525
},
2626
"dependencies": {
27-
"apollo-graphql": "^0.9.3"
27+
"apollo-graphql": "^0.9.5"
2828
},
2929
"peerDependencies": {
3030
"graphql": "^15.5.3"

subgraph-js/src/__tests__/printSubgraphSchema.test.ts

+56
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,60 @@ describe('printSubgraphSchema', () => {
176176
"
177177
`);
178178
});
179+
180+
it('prints directives on schema definition nodes', () => {
181+
const schema = buildSubgraphSchema(fixtures[1].typeDefs);
182+
expect(printSubgraphSchema(schema)).toMatchInlineSnapshot(`
183+
"schema @contact(name: \\"books-team\\", url: \\"mailto:[email protected]\\", description: \\"books\\") {
184+
query: Query
185+
}
186+
187+
directive @stream on FIELD
188+
189+
directive @transform(from: String!) on FIELD
190+
191+
directive @contact(name: String!, url: String, description: String) on SCHEMA
192+
193+
directive @cacheControl(maxAge: Int, scope: CacheControlScope, inheritMaxAge: Boolean) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
194+
195+
enum CacheControlScope {
196+
PUBLIC
197+
PRIVATE
198+
}
199+
200+
type Library @key(fields: \\"id\\") {
201+
id: ID!
202+
name: String
203+
}
204+
205+
type Book @key(fields: \\"isbn\\") {
206+
isbn: String!
207+
title: String
208+
year: Int
209+
similarBooks: [Book]!
210+
metadata: [MetadataOrError]
211+
}
212+
213+
type KeyValue {
214+
key: String!
215+
value: String!
216+
}
217+
218+
type Error {
219+
code: Int
220+
message: String
221+
}
222+
223+
union MetadataOrError = KeyValue | Error
224+
225+
extend type Query {
226+
_entities(representations: [_Any!]!): [_Entity]!
227+
_service: _Service!
228+
book(isbn: String!): Book
229+
books: [Book]
230+
library(id: ID!): Library
231+
}
232+
"
233+
`);
234+
});
179235
});

subgraph-js/src/buildSubgraphSchema.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
addResolversToSchema,
1717
GraphQLResolverMap,
1818
} from 'apollo-graphql';
19-
import { federationDirectives, typeIncludesDirective } from './directives';
19+
import { directivesWithNoDefinitionNeeded, typeIncludesDirective } from './directives';
2020

2121
import { serviceField, entitiesField, EntityType } from './types';
2222

@@ -66,7 +66,7 @@ export function buildSubgraphSchema(
6666
modules,
6767
new GraphQLSchema({
6868
query: undefined,
69-
directives: [...specifiedDirectives, ...federationDirectives],
69+
directives: [...specifiedDirectives, ...directivesWithNoDefinitionNeeded],
7070
}),
7171
);
7272

0 commit comments

Comments
 (0)