Skip to content

feat(gateway): Implement @core v0.2, including "for" and core__Purpose support #957

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

Merged
merged 11 commits into from
Aug 18, 2021
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions docs/source/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,13 @@ This outputs the following supergraph schema that our gateway can use to route q

```graphql
schema
@core(feature: "https://specs.apollo.dev/core/v0.1"),
@core(feature: "https://specs.apollo.dev/join/v0.1")
@core(feature: "https://specs.apollo.dev/core/v0.2"),
@core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
{
query: Query
}

directive @core(feature: String!) repeatable on SCHEMA
directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA

directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION

Expand All @@ -189,6 +189,11 @@ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE

directive @join__graph(name: String!, url: String!) on ENUM_VALUE

enum core__Purpose {
EXECUTION
SECURITY
}

scalar join__FieldSet

enum join__Graph {
Expand Down
11 changes: 8 additions & 3 deletions docs/source/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,13 @@ Rover outputs the following schema:

```graphql
schema
@core(feature: "https://specs.apollo.dev/core/v0.1"),
@core(feature: "https://specs.apollo.dev/join/v0.1")
@core(feature: "https://specs.apollo.dev/core/v0.2"),
@core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
{
query: Query
}

directive @core(feature: String!) repeatable on SCHEMA
directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA

directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION

Expand All @@ -273,6 +273,11 @@ directive @join__owner(graph: join__Graph!) on OBJECT | INTERFACE

directive @join__graph(name: String!, url: String!) on ENUM_VALUE

enum core__Purpose {
EXECUTION
SECURITY
}

enum CURRENCY_CODE {
USD
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const [inaccessibleDefinition, schemaDefinition] = parse(`#graphql
directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
schema
# inaccessibleCoreUsage
@core(feature: "https://specs.apollo.dev/inaccessible/v0.1")
@core(feature: "https://specs.apollo.dev/inaccessible/v0.1", for: SECURITY)
# inaccessibleUsage
@inaccessible {
query: Query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export default {
},

print(value: GraphQLError, print) {
// Support printing GraphQLError.causes (from core-schema-js)
if ('causes' in value) {
// @ts-ignore
return print(value.causes.map((cause) => cause.message));
}
return print({
message: value.message,
code: value.extensions ? value.extensions.code : 'MISSING_ERROR',
Expand Down
21 changes: 21 additions & 0 deletions federation-js/src/coreSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,36 @@ import {
DirectiveLocation,
GraphQLNonNull,
GraphQLString,
GraphQLEnumType,
} from 'graphql';

const CorePurpose = new GraphQLEnumType({
name: 'core__Purpose',
values: {
EXECUTION: {
description:
'`EXECUTION` features provide metadata necessary to for operation execution.',
},
SECURITY: {
description:
'`SECURITY` features provide metadata necessary to securely resolve fields.',
},
},
});

export const CoreDirective = new GraphQLDirective({
name: 'core',
locations: [DirectiveLocation.SCHEMA],
args: {
feature: {
type: new GraphQLNonNull(GraphQLString),
},
as: {
type: GraphQLString,
},
for: {
type: CorePurpose,
},
},
isRepeatable: true,
});
36 changes: 30 additions & 6 deletions federation-js/src/service/__tests__/printSupergraphSdl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ describe('printSupergraphSdl', () => {
it('prints a fully composed schema correctly', () => {
expect(supergraphSdl).toMatchInlineSnapshot(`
"schema
@core(feature: \\"https://specs.apollo.dev/core/v0.1\\"),
@core(feature: \\"https://specs.apollo.dev/join/v0.1\\"),
@core(feature: \\"https://specs.apollo.dev/core/v0.2\\"),
@core(feature: \\"https://specs.apollo.dev/join/v0.1\\", for: EXECUTION),
@core(feature: \\"https://specs.apollo.dev/tag/v0.1\\")
{
query: Query
mutation: Mutation
}

directive @core(feature: String!) repeatable on SCHEMA
directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA

directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION

Expand Down Expand Up @@ -104,6 +104,18 @@ describe('printSupergraphSdl', () => {
retailPrice: String @join__field(graph: REVIEWS, requires: \\"price\\")
}

enum core__Purpose {
\\"\\"\\"
\`EXECUTION\` features provide metadata necessary to for operation execution.
\\"\\"\\"
EXECUTION

\\"\\"\\"
\`SECURITY\` features provide metadata necessary to securely resolve fields.
\\"\\"\\"
SECURITY
}

type Error {
code: Int
message: String
Expand Down Expand Up @@ -330,14 +342,14 @@ describe('printSupergraphSdl', () => {

expect(supergraphSdl).toMatchInlineSnapshot(`
"schema
@core(feature: \\"https://specs.apollo.dev/core/v0.1\\"),
@core(feature: \\"https://specs.apollo.dev/join/v0.1\\")
@core(feature: \\"https://specs.apollo.dev/core/v0.2\\"),
@core(feature: \\"https://specs.apollo.dev/join/v0.1\\", for: EXECUTION)
{
query: Query
mutation: Mutation
}

directive @core(feature: String!) repeatable on SCHEMA
directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA

directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION

Expand Down Expand Up @@ -400,6 +412,18 @@ describe('printSupergraphSdl', () => {
retailPrice: String @join__field(graph: REVIEWS, requires: \\"price\\")
}

enum core__Purpose {
\\"\\"\\"
\`EXECUTION\` features provide metadata necessary to for operation execution.
\\"\\"\\"
EXECUTION

\\"\\"\\"
\`SECURITY\` features provide metadata necessary to securely resolve fields.
\\"\\"\\"
SECURITY
}

type Error {
code: Int
message: String
Expand Down
15 changes: 11 additions & 4 deletions federation-js/src/service/printSupergraphSdl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,21 @@ function printCoreDirectives(schema: GraphQLSchema) {
otherKnownDirectiveNames.includes(name),
);
const otherKnownDirectiveSpecUrls = otherKnownDirectivesToInclude.map(
(name) => `https://specs.apollo.dev/${name}/v0.1`,
(name) => ({
feature: `https://specs.apollo.dev/${name}/v0.1`,
}),
);

return [
'https://specs.apollo.dev/core/v0.1',
'https://specs.apollo.dev/join/v0.1',
{ feature: 'https://specs.apollo.dev/core/v0.2' },
{ feature: 'https://specs.apollo.dev/join/v0.1', purpose: 'EXECUTION' },
...otherKnownDirectiveSpecUrls,
].map((feature) => `\n @core(feature: ${printStringLiteral(feature)})`);
].map(
({ feature, purpose }) =>
`\n @core(feature: ${printStringLiteral(feature)}${
purpose ? `, for: ${purpose}` : ''
})`,
);
}

export function printType(
Expand Down
2 changes: 1 addition & 1 deletion gateway-js/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

> 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.

- _Nothing yet! Stay tuned!_
- Introduce @core v0.2 support with the "for:" directive argument. The "for:" argument allows a @core directive to specify its criticality to the gateway (or any consumer). "for:" is optional - its absence means that the directive requires no additional support from the consumer. Its two available options `EXECUTION` and `SECURITY` both require explicit support from the consumer, else the consumer should fail to start / update to this unsupported schema. [PR #957](https://github.com/apollographql/federation/pull/942)

## v0.37.0

Expand Down
1 change: 1 addition & 0 deletions gateway-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"access": "public"
},
"dependencies": {
"@apollo/core-schema": "^0.1.0",
"@apollo/federation": "file:../federation-js",
"@apollo/query-planner": "file:../query-planner-js",
"@opentelemetry/api": "^1.0.1",
Expand Down
18 changes: 15 additions & 3 deletions gateway-js/src/__tests__/loadSupergraphSdlFromStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ describe('loadSupergraphSdlFromStorage', () => {
Object {
"id": "originalId-1234",
"supergraphSdl": "schema
@core(feature: \\"https://specs.apollo.dev/core/v0.1\\"),
@core(feature: \\"https://specs.apollo.dev/join/v0.1\\"),
@core(feature: \\"https://specs.apollo.dev/core/v0.2\\"),
@core(feature: \\"https://specs.apollo.dev/join/v0.1\\", for: EXECUTION),
@core(feature: \\"https://specs.apollo.dev/tag/v0.1\\")
{
query: Query
mutation: Mutation
}

directive @core(feature: String!) repeatable on SCHEMA
directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA

directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet) on FIELD_DEFINITION

Expand Down Expand Up @@ -111,6 +111,18 @@ describe('loadSupergraphSdlFromStorage', () => {
retailPrice: String @join__field(graph: REVIEWS, requires: \\"price\\")
}

enum core__Purpose {
\\"\\"\\"
\`EXECUTION\` features provide metadata necessary to for operation execution.
\\"\\"\\"
EXECUTION

\\"\\"\\"
\`SECURITY\` features provide metadata necessary to securely resolve fields.
\\"\\"\\"
SECURITY
}

type Error {
code: Int
message: String
Expand Down
Loading