Skip to content

Commit

Permalink
fix(makeRemoteExecutableSchema): stop sending entire document (#1352)
Browse files Browse the repository at this point in the history
= refactor makeRemoteExecutableSchema default resolvers to use delegateToSchema
= return promise where required in createSubscriber
= remove unused internal Delegator type
  • Loading branch information
yaacovCR committed Apr 7, 2020
1 parent 6147eae commit 8ae9b27
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 73 deletions.
10 changes: 0 additions & 10 deletions src/Interfaces.ts
Expand Up @@ -207,16 +207,6 @@ export interface IDelegateRequestOptions extends IDelegateToSchemaOptions {
request: Request;
}

export type Delegator = ({
document,
context,
variables,
}: {
document: DocumentNode;
context?: { [key: string]: any };
variables?: { [key: string]: any };
}) => any;

export interface MergeInfo {
delegate: (
type: 'query' | 'mutation' | 'subscription',
Expand Down
28 changes: 21 additions & 7 deletions src/delegate/delegateToSchema.ts
Expand Up @@ -8,13 +8,13 @@ import {
ExecutionResult,
GraphQLOutputType,
isSchema,
DocumentNode,
} from 'graphql';

import {
IDelegateToSchemaOptions,
IDelegateRequestOptions,
Fetcher,
Delegator,
SubschemaConfig,
isSubschemaConfig,
IGraphQLToolsResolveInfo,
Expand Down Expand Up @@ -202,9 +202,7 @@ export function delegateRequest({
subschemaConfig,
);

const executionResult:
| ExecutionResult
| Promise<ExecutionResult> = executor({
const executionResult = executor({
document: processedRequest.document,
context,
variables: processedRequest.variables,
Expand Down Expand Up @@ -263,7 +261,15 @@ function createExecutor(
rootValue: Record<string, any>,
context: Record<string, any>,
subschemaConfig?: SubschemaConfig,
): Delegator {
): ({
document,
context,
variables,
}: {
document: DocumentNode;
context?: Record<string, any>;
variables?: Record<string, any>;
}) => Promise<ExecutionResult> | ExecutionResult {
let fetcher: Fetcher;
let targetRootValue: Record<string, any> = rootValue;
if (subschemaConfig != null) {
Expand Down Expand Up @@ -308,7 +314,15 @@ function createSubscriber(
rootValue: Record<string, any>,
context: Record<string, any>,
subschemaConfig?: SubschemaConfig,
): Delegator {
): ({
document,
context,
variables,
}: {
document: DocumentNode;
context?: Record<string, any>;
variables?: Record<string, any>;
}) => Promise<AsyncIterator<ExecutionResult> | ExecutionResult> {
let link: ApolloLink;
let targetRootValue: Record<string, any> = rootValue;

Expand All @@ -332,7 +346,7 @@ function createSubscriber(
context: { graphqlContext },
};
const observable = executeLink(link, operation);
return observableToAsyncIterable(observable);
return Promise.resolve(observableToAsyncIterable(observable));
};
}

Expand Down
69 changes: 13 additions & 56 deletions src/wrap/makeRemoteExecutableSchema.ts
Expand Up @@ -2,30 +2,16 @@ import { ApolloLink } from 'apollo-link';
import {
GraphQLFieldResolver,
GraphQLSchema,
Kind,
GraphQLResolveInfo,
BuildSchemaOptions,
DocumentNode,
} from 'graphql';

import { Fetcher } from '../Interfaces';
import { buildSchema } from '../polyfills/index';
import { addTypenameToAbstract } from '../delegate/addTypenameToAbstract';
import { checkResultAndHandleErrors } from '../delegate/checkResultAndHandleErrors';

import linkToFetcher, { execute } from '../stitch/linkToFetcher';
import { observableToAsyncIterable } from '../stitch/observableToAsyncIterable';
import mapAsyncIterator from '../stitch/mapAsyncIterator';
import linkToFetcher from '../stitch/linkToFetcher';
import { delegateToSchema } from '../delegate';

import { wrapSchema } from './wrapSchema';

export type ResolverFn = (
rootValue?: any,
args?: any,
context?: any,
info?: GraphQLResolveInfo,
) => AsyncIterator<any>;

export default function makeRemoteExecutableSchema({
schema: schemaOrTypeDefs,
link,
Expand Down Expand Up @@ -68,50 +54,21 @@ export default function makeRemoteExecutableSchema({
export function defaultCreateRemoteResolver(
fetcher: Fetcher,
): GraphQLFieldResolver<any, any> {
return async (_root, _args, context, info) => {
const fragments = Object.keys(info.fragments).map(
(fragment) => info.fragments[fragment],
);
let query: DocumentNode = {
kind: Kind.DOCUMENT,
definitions: [info.operation, ...fragments],
};

query = addTypenameToAbstract(info.schema, query);

const result = await fetcher({
query,
variables: info.variableValues,
context: { graphqlContext: context },
return (_parent, _args, context, info) =>
delegateToSchema({
schema: { schema: info.schema, fetcher },
context,
info,
});
return checkResultAndHandleErrors(result, context, info);
};
}

export function defaultCreateRemoteSubscriptionResolver(
link: ApolloLink,
): GraphQLFieldResolver<any, any> {
return (_root, _args, context, info) => {
const fragments = Object.keys(info.fragments).map(
(fragment) => info.fragments[fragment],
);
let query: DocumentNode = {
kind: Kind.DOCUMENT,
definitions: [info.operation, ...fragments],
};

query = addTypenameToAbstract(info.schema, query);

const operation = {
query,
variables: info.variableValues,
context: { graphqlContext: context },
};

const observable = execute(link, operation);
const originalAsyncIterator = observableToAsyncIterable(observable);
return mapAsyncIterator(originalAsyncIterator, (result) => ({
[info.fieldName]: checkResultAndHandleErrors(result, context, info),
}));
};
return (_parent, _args, context, info) =>
delegateToSchema({
schema: { schema: info.schema, link },
context,
info,
});
}

0 comments on commit 8ae9b27

Please sign in to comment.