Skip to content

Commit

Permalink
Fixes issue ardatan#876, mirror delegateToSchema behavior for standalone
Browse files Browse the repository at this point in the history
  • Loading branch information
jjbeavers-lifeomic committed Jul 12, 2018
1 parent a259ccc commit 60d962d
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 13 deletions.
10 changes: 9 additions & 1 deletion src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ export type Transform = {
transformResult?: (result: Result) => Result;
};

export interface IGraphQLToolsResolveInfo extends GraphQLResolveInfo {
mergeInfo?: MergeInfo;
}

export interface IDelegateToSchemaOptions<TContext = { [key: string]: any }> {
schema: GraphQLSchema;
operation: Operation;
fieldName: string;
args?: { [key: string]: any };
context: TContext;
info: GraphQLResolveInfo;
info: IGraphQLToolsResolveInfo;
transforms?: Array<Transform>;
skipValidation?: boolean;
}
Expand All @@ -67,6 +71,10 @@ export type MergeInfo = {
transforms?: Array<Transform>,
) => any;
delegateToSchema<TContext>(options: IDelegateToSchemaOptions<TContext>): any;
fragments: Array<{
field: string;
fragment: string;
}>;
};

export type IFieldResolver<TSource, TContext> = (
Expand Down
20 changes: 16 additions & 4 deletions src/stitching/delegateToSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {
ArgumentNode,
DocumentNode,
FieldNode,
FragmentDefinitionNode,
Kind,
FragmentDefinitionNode,
OperationDefinitionNode,
SelectionSetNode,
SelectionNode,
Expand All @@ -30,6 +30,8 @@ import AddArgumentsAsVariables from '../transforms/AddArgumentsAsVariables';
import FilterToSchema from '../transforms/FilterToSchema';
import AddTypenameToAbstract from '../transforms/AddTypenameToAbstract';
import CheckResultAndHandleErrors from '../transforms/CheckResultAndHandleErrors';
import ExpandAbstractTypes from '../transforms/ExpandAbstractTypes';
import ReplaceFieldWithFragment from '../transforms/ReplaceFieldWithFragment';

export default function delegateToSchema(
options: IDelegateToSchemaOptions | GraphQLSchema,
Expand Down Expand Up @@ -65,13 +67,23 @@ async function delegateToSchemaImplementation(
variables: info.variableValues as Record<string, any>,
};

const transforms = [
let transforms = [
...(options.transforms || []),
new ExpandAbstractTypes(info.schema, options.schema)
];

if (info.mergeInfo && info.mergeInfo.fragments) {
transforms.push(
new ReplaceFieldWithFragment(options.schema, info.mergeInfo.fragments)
);
}

transforms = transforms.concat([
new AddArgumentsAsVariables(options.schema, args),
new FilterToSchema(options.schema),
new AddTypenameToAbstract(options.schema),
new CheckResultAndHandleErrors(info, options.fieldName),
];
new CheckResultAndHandleErrors(info, options.fieldName)
]);

const processedRequest = applyRequestTransforms(rawRequest, transforms);

Expand Down
7 changes: 2 additions & 5 deletions src/stitching/mergeSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,10 @@ function createMergeInfo(
delegateToSchema(options: IDelegateToSchemaOptions) {
return delegateToSchema({
...options,
transforms: [
...(options.transforms || []),
new ExpandAbstractTypes(options.info.schema, options.schema),
new ReplaceFieldWithFragment(options.schema, fragments),
],
transforms: options.transforms
});
},
fragments
};
}

Expand Down
108 changes: 108 additions & 0 deletions src/test/testDelegateToSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* tslint:disable:no-unused-expression */

import { expect } from 'chai';
import {
GraphQLSchema,
graphql
} from 'graphql';
import { propertySchema, bookingSchema, sampleData, Property } from './testingSchemas';
import delegateToSchema from '../stitching/delegateToSchema';
import mergeSchemas from '../stitching/mergeSchemas';
import { IResolvers } from '../Interfaces';

function findPropertyByLocationName (
properties: { [key: string]: Property },
name: string
): Property {
for (const key of Object.keys(properties)) {
const property = properties[key];
if (property.location.name === name) {
return property;
}
}
}

const COORDINATES_QUERY = `
query BookingCoordinates($bookingId: ID!) {
bookingById (id: $bookingId) {
property {
location {
coordinates
}
}
}
}
`;

function proxyResolvers (spec: string): IResolvers {
return {
Booking: {
property: {
fragment: '... on Booking { propertyId }',
resolve (booking, args, context, info) {
const delegateFn = spec === 'standalone' ? delegateToSchema :
info.mergeInfo.delegateToSchema;
return delegateFn({
schema: propertySchema,
operation: 'query',
fieldName: 'propertyById',
args: { id: booking.propertyId },
context,
info
});
}
}
},
Location: {
coordinates: {
fragment: '... on Location { name }',
resolve (location, args, context, info) {
const name = location.name;
return findPropertyByLocationName(sampleData.Property, name)
.location.coordinates;
}
}
}
};
}

const proxyTypeDefs = `
extend type Booking {
property: Property!
}
extend type Location {
coordinates: String!
}
`;

describe('stitching', () => {
describe('delegateToSchema', () => {
['standalone', 'info.mergeInfo'].forEach(spec => {
context(spec, () => {
let schema: GraphQLSchema;
before(() => {
schema = mergeSchemas({
schemas: [bookingSchema, propertySchema, proxyTypeDefs],
resolvers: proxyResolvers(spec)
});
});
it('should add fragments for deep types', async () => {
const result = await graphql(schema, COORDINATES_QUERY,
{}, {}, { bookingId: 'b1' });

expect(result).to.deep.equal({
data: {
bookingById: {
property: {
location: {
coordinates: sampleData.Property.p1.location.coordinates
}
}
}
}
});
});
});
});
});
});
12 changes: 9 additions & 3 deletions src/test/testingSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ import makeRemoteExecutableSchema, {
import introspectSchema from '../stitching/introspectSchema';
import { PubSub } from 'graphql-subscriptions';

export type Location = {
name: string;
coordinates: string;
};

export type Property = {
id: string;
name: string;
location: {
name: string;
};
location: Location;
};

export type Product = {
Expand Down Expand Up @@ -84,20 +87,23 @@ export const sampleData: {
name: 'Super great hotel',
location: {
name: 'Helsinki',
coordinates: '60.1698° N, 24.9383° E'
},
},
p2: {
id: 'p2',
name: 'Another great hotel',
location: {
name: 'San Francisco',
coordinates: '37.7749° N, 122.4194° W'
},
},
p3: {
id: 'p3',
name: 'BedBugs - The Affordable Hostel',
location: {
name: 'Helsinki',
coordinates: '60.1699° N, 24.9384° E'
},
},
},
Expand Down
1 change: 1 addition & 0 deletions src/test/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ import './testTransforms';
import './testAlternateMergeSchemas';
import './testErrors';
import './testDirectives';
import './testDelegateToSchema';

0 comments on commit 60d962d

Please sign in to comment.