diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c1a6750868..46073d97e28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Include readme for npm packages * Update peerDependencies version for micro [PR #671](https://github.com/apollographql/apollo-server/pull/671) * Corrected the hapi example both in the README.md [PR #689] [Issue #689] +* Change GraphqlOptions to also accept context as a function[PR #679](https://github.com/apollographql/apollo-server/pull/679) ### v1.1.6 * Fixes bug where CORS would not allow `Access-Control-Allow-Origin: *` with credential 'include', changed to 'same-origin' [Issue #514](https://github.com/apollographql/apollo-server/issues/514) diff --git a/packages/apollo-server-core/src/runHttpQuery.ts b/packages/apollo-server-core/src/runHttpQuery.ts index df156784c99..0990161005b 100644 --- a/packages/apollo-server-core/src/runHttpQuery.ts +++ b/packages/apollo-server-core/src/runHttpQuery.ts @@ -27,6 +27,10 @@ function isQueryOperation(query: DocumentNode, operationName: string) { return operationAST.operation === 'query'; } +function isFunction(arg: any): arg is Function { + return typeof arg === 'function'; +} + export async function runHttpQuery(handlerArguments: Array, request: HttpQueryRequest): Promise { let isGetRequest: boolean = false; let optionsObject: GraphQLOptions; @@ -97,19 +101,18 @@ export async function runHttpQuery(handlerArguments: Array, request: HttpQu } } - // Shallow clone context for queries in batches. This allows - // users to distinguish multiple queries in the batch and to - // modify the context object without interfering with each other. - let context = optionsObject.context; - if (isBatch) { - context = Object.assign({}, context || {}); + let context = optionsObject.context || {}; + if (isFunction(context)) { + context = context(); + } else if (isBatch) { + context = Object.assign(Object.create(Object.getPrototypeOf(context)), context); } let params = { schema: optionsObject.schema, query: query, variables: variables, - context: context, + context, rootValue: optionsObject.rootValue, operationName: operationName, logFunction: optionsObject.logFunction, diff --git a/packages/apollo-server-integration-testsuite/src/index.ts b/packages/apollo-server-integration-testsuite/src/index.ts index 8567e580c02..d4731bea28c 100644 --- a/packages/apollo-server-integration-testsuite/src/index.ts +++ b/packages/apollo-server-integration-testsuite/src/index.ts @@ -522,6 +522,41 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => { }); }); + it('executes batch context if it is a function', async () => { + let callCount = 0; + app = await createApp({graphqlOptions: { + schema, + context: () => { + callCount++; + return ({testField: 'expected'}); + }, + }}); + const expected = [ + { + data: { + testContext: 'expected', + }, + }, + { + data: { + testContext: 'expected', + }, + }, + ]; + const req = request(app) + .post('/graphql') + .send([{ + query: 'query test{ testContext }', + }, { + query: 'query test{ testContext }', + }]); + return req.then((res) => { + expect(callCount).to.equal(2); + expect(res.status).to.equal(200); + return expect(res.body).to.deep.equal(expected); + }); + }); + it('can handle a request with a mutation', async () => { app = await createApp(); const expected = {