Skip to content
This repository has been archived by the owner on Mar 20, 2023. It is now read-only.

Commit

Permalink
Allow to replace default execute function (#391)
Browse files Browse the repository at this point in the history
This PR allows providing your own `execute` function instead of the default one from the `graphql-js`.
It’s a small change that adds a lot of flexibility since you can wrap standard `execute` and it opens new possibilities for middlewares. 

Personally, I need it to proxy calls to 3rd-party APIs.
It’s an alternative to #253 but introduces less code and more flexible mechanism.
It’s very important for us as it will be the last change required to switch [graphql-faker](https://github.com/APIs-guru/graphql-faker) from custom forks of `graphql-js` and `graphql-express`.
@wincent @leebyron Can you please review it?
  • Loading branch information
IvanGoncharov authored Apr 7, 2019
1 parent 898a033 commit 40a6a42
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ The `graphqlHTTP` function accepts the following options:
* **`customValidateFn`**: An optional function which will be used to validate
instead of default `validate` from `graphql-js`.

* **`customExecuteFn`**: An optional function which will be used to execute
instead of default `execute` from `graphql-js`.

* **`customFormatErrorFn`**: An optional function which will be used to format any
errors produced by fulfilling a GraphQL operation. If no function is
provided, GraphQL's default spec-compliant [`formatError`][] function will be used.
Expand Down
32 changes: 32 additions & 0 deletions src/__tests__/http-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
GraphQLError,
BREAK,
validate,
execute,
} from 'graphql';
import graphqlHTTP from '../';

Expand Down Expand Up @@ -2000,6 +2001,37 @@ describe('test harness', () => {
});
});

describe('Custom execute', () => {
it('allow to replace default execute.', async () => {
const app = server();

let seenExecuteArgs;

get(
app,
urlString(),
graphqlHTTP(() => {
return {
schema: TestSchema,
async customExecuteFn(args) {
seenExecuteArgs = args;
const result: any = await Promise.resolve(execute(args));
result.data.test2 = 'Modification';
return result;
},
};
}),
);

const response = await request(app).get(urlString({ query: '{test}' }));

expect(response.text).to.equal(
'{"data":{"test":"Hello World","test2":"Modification"}}',
);
expect(seenExecuteArgs).to.not.equal(null);
});
});

describe('Custom result extensions', () => {
it('allows for adding extensions', async () => {
const app = server();
Expand Down
20 changes: 15 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getOperationAST,
specifiedRules,
} from 'graphql';
import type { ExecutionArgs, ExecutionResult } from 'graphql';
import httpError from 'http-errors';
import url from 'url';

Expand Down Expand Up @@ -51,6 +52,7 @@ export type Options =
) => OptionsResult)
| OptionsResult;
export type OptionsResult = OptionsData | Promise<OptionsData>;

export type OptionsData = {
/**
* A GraphQL schema from graphql-js.
Expand Down Expand Up @@ -88,6 +90,12 @@ export type OptionsData = {
rules: $ReadOnlyArray<any>,
) => $ReadOnlyArray<GraphQLError>,

/**
* An optional function which will be used to execute instead of default `execute`
* from `graphql-js`.
*/
customExecuteFn?: ?(args: ExecutionArgs) => Promise<ExecutionResult>,

/**
* An optional function which will be used to format any errors produced by
* fulfilling a GraphQL operation. If no function is provided, GraphQL's
Expand Down Expand Up @@ -176,6 +184,7 @@ function graphqlHTTP(options: Options): Middleware {
let pretty;
let formatErrorFn = formatError;
let validateFn = validate;
let executeFn = execute;
let extensionsFn;
let showGraphiQL;
let query;
Expand Down Expand Up @@ -302,15 +311,15 @@ function graphqlHTTP(options: Options): Middleware {
}
// Perform the execution, reporting any errors creating the context.
try {
return execute(
return executeFn({
schema,
documentAST,
document: documentAST,
rootValue,
context,
variables,
contextValue: context,
variableValues: variables,
operationName,
fieldResolver,
);
});
} catch (contextError) {
// Return 400: Bad Request if any execution context errors exist.
response.statusCode = 400;
Expand Down Expand Up @@ -407,6 +416,7 @@ function graphqlHTTP(options: Options): Middleware {
}

validateFn = optionsData.customValidateFn || validateFn;
executeFn = optionsData.customExecuteFn || executeFn;
formatErrorFn =
optionsData.customFormatErrorFn ||
optionsData.formatError ||
Expand Down

0 comments on commit 40a6a42

Please sign in to comment.