diff --git a/packages/apollo-server-core/src/ApolloServer.ts b/packages/apollo-server-core/src/ApolloServer.ts index 9d4bfd4dcb1..708bfbc171b 100644 --- a/packages/apollo-server-core/src/ApolloServer.ts +++ b/packages/apollo-server-core/src/ApolloServer.ts @@ -50,8 +50,9 @@ import { PlaygroundRenderPageOptions, } from './playground'; -import createSHA from './utils/createSHA'; import { generateSchemaHash } from './utils/schemaHash'; +import { isDirectiveDefined } from './utils/isDirectiveDefined'; +import createSHA from './utils/createSHA'; import { processGraphQLRequest, GraphQLRequestContext, @@ -270,19 +271,22 @@ export class ApolloServerBase { // We augment the typeDefs with the @cacheControl directive and associated // scope enum, so makeExecutableSchema won't fail SDL validation - augmentedTypeDefs.push( - gql` - enum CacheControlScope { - PUBLIC - PRIVATE - } - directive @cacheControl( - maxAge: Int - scope: CacheControlScope - ) on FIELD_DEFINITION | OBJECT | INTERFACE - `, - ); + if (!isDirectiveDefined(augmentedTypeDefs, 'cacheControl')) { + augmentedTypeDefs.push( + gql` + enum CacheControlScope { + PUBLIC + PRIVATE + } + + directive @cacheControl( + maxAge: Int + scope: CacheControlScope + ) on FIELD_DEFINITION | OBJECT | INTERFACE + `, + ); + } if (this.uploadsConfig) { const { GraphQLUpload } = require('graphql-upload'); diff --git a/packages/apollo-server-core/src/__tests__/isDirectiveDefined.ts b/packages/apollo-server-core/src/__tests__/isDirectiveDefined.ts new file mode 100644 index 00000000000..e3353064f7b --- /dev/null +++ b/packages/apollo-server-core/src/__tests__/isDirectiveDefined.ts @@ -0,0 +1,44 @@ +import { gql } from '../'; +import { isDirectiveDefined } from '../utils/isDirectiveDefined'; + +describe('isDirectiveDefined', () => { + it('returns false when a directive is not defined', () => { + expect( + isDirectiveDefined( + [ + gql` + type Query { + hello: String + } + `, + ], + 'cacheControl', + ), + ).toBe(false); + }); + + it('returns true when a directive is defined', () => { + expect( + isDirectiveDefined( + [ + gql` + type Query { + hello: String + } + + enum CacheControlScope { + PUBLIC + PRIVATE + } + + directive @cacheControl( + maxAge: Int + scope: CacheControlScope + ) on FIELD_DEFINITION | OBJECT | INTERFACE + `, + ], + 'cacheControl', + ), + ).toBe(true); + }); +}); diff --git a/packages/apollo-server-core/src/utils/isDirectiveDefined.ts b/packages/apollo-server-core/src/utils/isDirectiveDefined.ts new file mode 100644 index 00000000000..4523573b851 --- /dev/null +++ b/packages/apollo-server-core/src/utils/isDirectiveDefined.ts @@ -0,0 +1,13 @@ +import { DocumentNode, Kind } from 'graphql/language'; + +export const isDirectiveDefined = ( + typeDefs: DocumentNode[], + directiveName: string, +) => + typeDefs.some(typeDef => + typeDef.definitions.some( + definition => + definition.kind === Kind.DIRECTIVE_DEFINITION && + definition.name.value === directiveName, + ), + );