Added an option to support additional extensions

(Originally #934, tweaked by @glasser.)
This commit is contained in:
Sebastian 2018-04-02 22:49:43 -03:00 committed by David Glasser
parent 38c8713f4d
commit 2acf5654c3
5 changed files with 59 additions and 4 deletions

View file

@ -107,13 +107,16 @@ const GraphQLOptions = {
validationRules?: Array<ValidationRule>, validationRules?: Array<ValidationRule>,
// a function applied to each graphQL execution result // a function applied to each graphQL execution result
formatResponse?: Function formatResponse?: Function,
// a custom default field resolver // a custom default field resolver
fieldResolver?: Function fieldResolver?: Function,
// a boolean that will print additional debug logging if execution errors occur // a boolean that will print additional debug logging if execution errors occur
debug?: boolean debug?: boolean,
// (optional) extra GraphQL extensions from graphql-extensions
extensions?: Array<GraphQLExtension>
} }
``` ```

View file

@ -19,6 +19,7 @@ import { GraphQLExtension } from 'graphql-extensions';
* - (optional) formatResponse: a function applied to each graphQL execution result * - (optional) formatResponse: a function applied to each graphQL execution result
* - (optional) fieldResolver: a custom default field resolver * - (optional) fieldResolver: a custom default field resolver
* - (optional) debug: a boolean that will print additional debug logging if execution errors occur * - (optional) debug: a boolean that will print additional debug logging if execution errors occur
* - (optional) extensions: an array of GraphQLExtension
* *
*/ */
export interface GraphQLServerOptions< export interface GraphQLServerOptions<
@ -39,6 +40,7 @@ export interface GraphQLServerOptions<
tracing?: boolean; tracing?: boolean;
// cacheControl?: boolean | CacheControlExtensionOptions; // cacheControl?: boolean | CacheControlExtensionOptions;
cacheControl?: boolean | any; cacheControl?: boolean | any;
extensions?: Array<typeof GraphQLExtension | GraphQLExtension>;
} }
export default GraphQLServerOptions; export default GraphQLServerOptions;

View file

@ -255,6 +255,7 @@ export async function runHttpQuery(
tracing: optionsObject.tracing, tracing: optionsObject.tracing,
cacheControl: optionsObject.cacheControl, cacheControl: optionsObject.cacheControl,
request: request.request, request: request.request,
extensions: optionsObject.extensions,
}; };
if (optionsObject.formatParams) { if (optionsObject.formatParams) {

View file

@ -20,6 +20,7 @@ import { LogAction, LogStep } from './logging';
// environment. // environment.
import { makeCompatible } from 'meteor-promise'; import { makeCompatible } from 'meteor-promise';
import Fiber = require('fibers'); import Fiber = require('fibers');
import { GraphQLExtensionStack, GraphQLExtension } from 'graphql-extensions';
makeCompatible(Promise, Fiber); makeCompatible(Promise, Fiber);
const queryType = new GraphQLObjectType({ const queryType = new GraphQLObjectType({
@ -366,6 +367,53 @@ describe('runQuery', () => {
}); });
}); });
describe('graphql extensions', () => {
class CustomExtension implements GraphQLExtension<any> {
format(): [string, any] {
return ['customExtension', { foo: 'bar' }];
}
}
it('creates the extension stack', async () => {
const query = `{ testString }`;
const expected = { testString: 'it works' };
const extensions = [CustomExtension];
return runQuery({
schema: new GraphQLSchema({
query: new GraphQLObjectType({
name: 'QueryType',
fields: {
testString: {
type: GraphQLString,
resolve(root, args, context) {
expect(context._extensionStack).to.be.instanceof(
GraphQLExtensionStack,
);
expect(
context._extensionStack.extensions[0],
).to.be.instanceof(CustomExtension);
},
},
},
}),
}),
query,
extensions,
});
});
it('runs format response from extensions', async () => {
const query = `{ testString }`;
const expected = { testString: 'it works' };
const extensions = [CustomExtension];
return runQuery({ schema, query: query, extensions }).then(res => {
return expect(res.extensions).to.deep.equal({
customExtension: { foo: 'bar' },
});
});
});
});
describe('async_hooks', () => { describe('async_hooks', () => {
let asyncHooks; let asyncHooks;
let asyncHook; let asyncHook;

View file

@ -64,6 +64,7 @@ export interface QueryOptions {
// cacheControl?: boolean | CacheControlExtensionOptions; // cacheControl?: boolean | CacheControlExtensionOptions;
cacheControl?: boolean | any; cacheControl?: boolean | any;
request: Request; request: Request;
extensions?: Array<typeof GraphQLExtension | GraphQLExtension>;
} }
function isQueryOperation(query: DocumentNode, operationName: string) { function isQueryOperation(query: DocumentNode, operationName: string) {
@ -98,7 +99,7 @@ function doRunQuery(options: QueryOptions): Promise<GraphQLResponse> {
logFunction({ action: LogAction.request, step: LogStep.start }); logFunction({ action: LogAction.request, step: LogStep.start });
const context = options.context || {}; const context = options.context || {};
let extensions = []; let extensions = options.extensions !== undefined ? options.extensions : [];
if (options.tracing) { if (options.tracing) {
extensions.push(TracingExtension); extensions.push(TracingExtension);
} }