From ccff9c35ed93ee276daa1933b516b29de1132950 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 8 Feb 2019 13:58:50 -0500 Subject: [PATCH 1/4] Pass noLocation:true to schema parser by default. --- .../apollo-server-core/src/ApolloServer.ts | 9 +++++ packages/apollo-server-core/src/types.ts | 35 +++++++++++-------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/packages/apollo-server-core/src/ApolloServer.ts b/packages/apollo-server-core/src/ApolloServer.ts index 6c58cbd49c3..891c0d3020e 100644 --- a/packages/apollo-server-core/src/ApolloServer.ts +++ b/packages/apollo-server-core/src/ApolloServer.ts @@ -134,6 +134,7 @@ export class ApolloServerBase { schemaDirectives, modules, typeDefs, + parseOptions, introspection, mocks, mockEntireSchema, @@ -292,6 +293,14 @@ export class ApolloServerBase { typeDefs: augmentedTypeDefs, schemaDirectives, resolvers, + parseOptions: { + // Since ApolloServer does not use the location/token information the + // graphql/language/parser attaches to the schema, we can save some + // memory (and potentially some parsing time) with this default. + noLocation: true, + // Other options can be passed into the ApolloServerBase constructor. + ...parseOptions, + }, }); } diff --git a/packages/apollo-server-core/src/types.ts b/packages/apollo-server-core/src/types.ts index 36d050ad487..88358a7696a 100644 --- a/packages/apollo-server-core/src/types.ts +++ b/packages/apollo-server-core/src/types.ts @@ -1,5 +1,10 @@ import { GraphQLSchema, DocumentNode } from 'graphql'; -import { SchemaDirectiveVisitor, IResolvers, IMocks } from 'graphql-tools'; +import { + SchemaDirectiveVisitor, + IResolvers, + IMocks, + GraphQLParseOptions, +} from 'graphql-tools'; import { ConnectionContext } from 'subscriptions-transport-ws'; import WebSocket from 'ws'; import { GraphQLExtension } from 'graphql-extensions'; @@ -42,23 +47,25 @@ export interface SubscriptionServerOptions { onDisconnect?: (websocket: WebSocket, context: ConnectionContext) => any; } +type BaseConfig = Pick< + GraphQLOptions>, + | 'formatError' + | 'debug' + | 'rootValue' + | 'validationRules' + | 'formatResponse' + | 'fieldResolver' + | 'tracing' + | 'dataSources' + | 'cache' +>; + // This configuration is shared between all integrations and should include // fields that are not specific to a single integration -export interface Config - extends Pick< - GraphQLOptions>, - | 'formatError' - | 'debug' - | 'rootValue' - | 'validationRules' - | 'formatResponse' - | 'fieldResolver' - | 'tracing' - | 'dataSources' - | 'cache' - > { +export interface Config extends BaseConfig { modules?: GraphQLSchemaModule[]; typeDefs?: DocumentNode | Array; + parseOptions?: GraphQLParseOptions; resolvers?: IResolvers; schema?: GraphQLSchema; schemaDirectives?: Record; From 06459a16c6f5d8cebe56df12afe8c007e6c93387 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 12 Feb 2019 10:01:21 -0500 Subject: [PATCH 2/4] Revert noLocation:true as default, but preserve parseOptions. Thanks to @abernix for his thoughtful objections in this comment: https://github.com/apollographql/apollo-server/pull/2289#pullrequestreview-202158307 --- packages/apollo-server-core/src/ApolloServer.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/apollo-server-core/src/ApolloServer.ts b/packages/apollo-server-core/src/ApolloServer.ts index 891c0d3020e..26638c0aa5d 100644 --- a/packages/apollo-server-core/src/ApolloServer.ts +++ b/packages/apollo-server-core/src/ApolloServer.ts @@ -293,14 +293,7 @@ export class ApolloServerBase { typeDefs: augmentedTypeDefs, schemaDirectives, resolvers, - parseOptions: { - // Since ApolloServer does not use the location/token information the - // graphql/language/parser attaches to the schema, we can save some - // memory (and potentially some parsing time) with this default. - noLocation: true, - // Other options can be passed into the ApolloServerBase constructor. - ...parseOptions, - }, + parseOptions, }); } From 44f2dc8f7f01af958fabcd9cedc5e849e229d48a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 12 Feb 2019 10:23:59 -0500 Subject: [PATCH 3/4] Reuse parseOptions when parsing queries. --- packages/apollo-server-core/src/ApolloServer.ts | 9 +++++++-- packages/apollo-server-core/src/graphqlOptions.ts | 3 +++ packages/apollo-server-core/src/requestPipeline.ts | 12 +++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/apollo-server-core/src/ApolloServer.ts b/packages/apollo-server-core/src/ApolloServer.ts index 26638c0aa5d..7b80aa77beb 100644 --- a/packages/apollo-server-core/src/ApolloServer.ts +++ b/packages/apollo-server-core/src/ApolloServer.ts @@ -1,4 +1,4 @@ -import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools'; +import { makeExecutableSchema, addMockFunctionsToSchema, GraphQLParseOptions } from 'graphql-tools'; import { Server as HttpServer } from 'http'; import { execute, @@ -124,6 +124,8 @@ export class ApolloServerBase { // on the same operation to be executed immediately. private documentStore?: InMemoryLRUCache; + private parseOptions: GraphQLParseOptions; + // The constructor should be universal across all environments. All environment specific behavior should be set by adding or overriding methods constructor(config: Config) { if (!config) throw new Error('ApolloServer requires options.'); @@ -134,7 +136,7 @@ export class ApolloServerBase { schemaDirectives, modules, typeDefs, - parseOptions, + parseOptions = {}, introspection, mocks, mockEntireSchema, @@ -297,6 +299,8 @@ export class ApolloServerBase { }); } + this.parseOptions = parseOptions; + if (mocks || (typeof mockEntireSchema !== 'undefined' && mocks !== false)) { addMockFunctionsToSchema({ schema: this.schema, @@ -548,6 +552,7 @@ export class ApolloServerBase { any, any >, + parseOptions: this.parseOptions, ...this.requestOptions, } as GraphQLOptions; } diff --git a/packages/apollo-server-core/src/graphqlOptions.ts b/packages/apollo-server-core/src/graphqlOptions.ts index c1e36ffa2c6..3511f29641a 100644 --- a/packages/apollo-server-core/src/graphqlOptions.ts +++ b/packages/apollo-server-core/src/graphqlOptions.ts @@ -9,6 +9,7 @@ import { CacheControlExtensionOptions } from 'apollo-cache-control'; import { KeyValueCache, InMemoryLRUCache } from 'apollo-server-caching'; import { DataSource } from 'apollo-datasource'; import { ApolloServerPlugin } from 'apollo-server-plugin-base'; +import { GraphQLParseOptions } from 'graphql-tools'; /* * GraphQLServerOptions @@ -22,6 +23,7 @@ import { ApolloServerPlugin } from 'apollo-server-plugin-base'; * - (optional) fieldResolver: a custom default field resolver * - (optional) debug: a boolean that will print additional debug logging if execution errors occur * - (optional) extensions: an array of functions which create GraphQLExtensions (each GraphQLExtension object is used for one request) + * - (optional) parseOptions: options to pass when parsing schemas and queries * */ export interface GraphQLServerOptions< @@ -44,6 +46,7 @@ export interface GraphQLServerOptions< persistedQueries?: PersistedQueryOptions; plugins?: ApolloServerPlugin[]; documentStore?: InMemoryLRUCache; + parseOptions?: GraphQLParseOptions; } export type DataSources = { diff --git a/packages/apollo-server-core/src/requestPipeline.ts b/packages/apollo-server-core/src/requestPipeline.ts index 6d8d9fd0a37..21cfe5eb8ce 100644 --- a/packages/apollo-server-core/src/requestPipeline.ts +++ b/packages/apollo-server-core/src/requestPipeline.ts @@ -45,6 +45,7 @@ import { import { Dispatcher } from './utils/dispatcher'; import { InMemoryLRUCache, KeyValueCache } from 'apollo-server-caching'; +import { GraphQLParseOptions } from 'graphql-tools'; export { GraphQLRequest, @@ -78,6 +79,8 @@ export interface GraphQLRequestPipelineConfig { plugins?: ApolloServerPlugin[]; documentStore?: InMemoryLRUCache; + + parseOptions?: GraphQLParseOptions; } export type DataSources = { @@ -194,7 +197,7 @@ export async function processGraphQLRequest( ); try { - requestContext.document = parse(query); + requestContext.document = parse(query, config.parseOptions); parsingDidEnd(); } catch (syntaxError) { parsingDidEnd(syntaxError); @@ -306,13 +309,16 @@ export async function processGraphQLRequest( requestDidEnd(); } - function parse(query: string): DocumentNode { + function parse( + query: string, + parseOptions?: GraphQLParseOptions, + ): DocumentNode { const parsingDidEnd = extensionStack.parsingDidStart({ queryString: query, }); try { - return graphql.parse(query); + return graphql.parse(query, parseOptions); } finally { parsingDidEnd(); } From 29870ab954754a9bee1ed1a61f0e0600db24c1be Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 12 Feb 2019 10:51:42 -0500 Subject: [PATCH 4/4] Humor prettier complaints. --- packages/apollo-server-core/src/ApolloServer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/apollo-server-core/src/ApolloServer.ts b/packages/apollo-server-core/src/ApolloServer.ts index 7b80aa77beb..5d7cb559330 100644 --- a/packages/apollo-server-core/src/ApolloServer.ts +++ b/packages/apollo-server-core/src/ApolloServer.ts @@ -1,4 +1,8 @@ -import { makeExecutableSchema, addMockFunctionsToSchema, GraphQLParseOptions } from 'graphql-tools'; +import { + makeExecutableSchema, + addMockFunctionsToSchema, + GraphQLParseOptions, +} from 'graphql-tools'; import { Server as HttpServer } from 'http'; import { execute,