mirror of
https://github.com/vale981/apollo-server
synced 2025-03-04 17:21:42 -05:00
Add support for resolveObject
to query execution
This commit is contained in:
parent
3413c59ace
commit
bb67584a22
3 changed files with 63 additions and 8 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -3,6 +3,9 @@
|
|||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@apollographql/apollo-tools": {
|
||||
"version": "file:../apollo-tooling/packages/apollo-tools"
|
||||
},
|
||||
"@apollographql/apollo-upload-server": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@apollographql/apollo-upload-server/-/apollo-upload-server-5.0.3.tgz",
|
||||
|
@ -6080,12 +6083,17 @@
|
|||
"dev": true
|
||||
},
|
||||
"graphql": {
|
||||
"version": "14.0.2",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz",
|
||||
"integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==",
|
||||
"version": "file:../graphql-js/dist",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"iterall": "^1.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"iterall": {
|
||||
"version": "1.2.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"graphql-extensions": {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"node": ">=6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollographql/apollo-tools": "file:../apollo-tooling/packages/apollo-tools",
|
||||
"apollo-cache-control": "file:packages/apollo-cache-control",
|
||||
"apollo-datasource": "file:packages/apollo-datasource",
|
||||
"apollo-datasource-rest": "file:packages/apollo-datasource-rest",
|
||||
|
@ -94,7 +95,7 @@
|
|||
"express": "4.16.4",
|
||||
"fibers": "3.0.0",
|
||||
"form-data": "2.3.3",
|
||||
"graphql": "14.0.2",
|
||||
"graphql": "file:../graphql-js/dist",
|
||||
"graphql-subscriptions": "1.0.0",
|
||||
"graphql-tag": "2.10.0",
|
||||
"graphql-tools": "4.0.3",
|
||||
|
|
|
@ -8,6 +8,8 @@ import {
|
|||
GraphQLResolveInfo,
|
||||
ExecutionArgs,
|
||||
DocumentNode,
|
||||
ResponsePath,
|
||||
FieldNode,
|
||||
} from 'graphql';
|
||||
|
||||
import { Request } from 'apollo-server-env';
|
||||
|
@ -19,6 +21,8 @@ import {
|
|||
} from 'apollo-server-core/dist/requestPipelineAPI';
|
||||
export { GraphQLResponse };
|
||||
|
||||
import { GraphQLObjectResolver } from '@apollographql/apollo-tools';
|
||||
|
||||
export type EndHandler = (...errors: Array<Error>) => void;
|
||||
// A StartHandlerInvoker is a function that, given a specific GraphQLExtension,
|
||||
// finds a specific StartHandler on that extension and calls it with appropriate
|
||||
|
@ -199,6 +203,15 @@ function wrapField(field: GraphQLField<any, any>): void {
|
|||
const fieldResolver = field.resolve;
|
||||
|
||||
field.resolve = (source, args, context, info) => {
|
||||
// This is a bit of a hack, but since `ResponsePath` is a linked list,
|
||||
// a new object gets created every time a path segment is added.
|
||||
// So we can use that to share our `whenObjectResolved` promise across
|
||||
// all field resolvers for the same object.
|
||||
const parentPath = info.path.prev as ResponsePath & {
|
||||
__fields: Record<string, ReadonlyArray<FieldNode>>;
|
||||
__whenObjectResolved: Promise<any>;
|
||||
};
|
||||
|
||||
const extensionStack = context && context._extensionStack;
|
||||
const handler =
|
||||
(extensionStack &&
|
||||
|
@ -207,12 +220,45 @@ function wrapField(field: GraphQLField<any, any>): void {
|
|||
/* do nothing */
|
||||
});
|
||||
|
||||
// If no resolver has been defined for a field, use the default field resolver
|
||||
// (which matches the behavior of graphql-js when there is no explicit resolve function defined).
|
||||
const resolveObject: GraphQLObjectResolver<
|
||||
any,
|
||||
any
|
||||
> = (info.parentType as any).resolveObject;
|
||||
|
||||
let whenObjectResolved: Promise<any> | undefined;
|
||||
|
||||
if (parentPath && resolveObject) {
|
||||
whenObjectResolved = parentPath.__whenObjectResolved;
|
||||
if (!whenObjectResolved) {
|
||||
whenObjectResolved = (async () => {
|
||||
return resolveObject(source, context, info);
|
||||
})();
|
||||
parentPath.__whenObjectResolved = whenObjectResolved;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const result = (fieldResolver ||
|
||||
// If no resolver has been defined for a field, use either the configured
|
||||
// field resolver or the default field resolver
|
||||
// (which matches the behavior of graphql-js when there is no explicit
|
||||
// resolve function defined).
|
||||
// XXX: Can't this be pulled up to the top of `wrapField` and only
|
||||
// assigned once? It seems `extensionStack.fieldResolver` isn't set
|
||||
// anywhere?
|
||||
const actualFieldResolver =
|
||||
fieldResolver ||
|
||||
(extensionStack && extensionStack.fieldResolver) ||
|
||||
defaultFieldResolver)(source, args, context, info);
|
||||
defaultFieldResolver;
|
||||
|
||||
let result: any;
|
||||
if (whenObjectResolved) {
|
||||
result = whenObjectResolved.then((resolvedObject: any) => {
|
||||
return actualFieldResolver(resolvedObject, args, context, info);
|
||||
});
|
||||
} else {
|
||||
result = actualFieldResolver(source, args, context, info);
|
||||
}
|
||||
|
||||
// Call the stack's handlers either immediately (if result is not a
|
||||
// Promise) or once the Promise is done. Then return that same
|
||||
// maybe-Promise value.
|
||||
|
|
Loading…
Add table
Reference in a new issue