Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix] allow renaming of subscription root fields #1104

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,10 @@
[@hayes](https://github.com/hayes) in [#1062](https://github.com/apollographql/graphql-tools/pull/1062)
* Make `mergeSchemas` optionally merge directive definitions. <br/>
[@freiksenet](https://github.com/freiksenet) in [#1003](https://github.com/apollographql/graphql-tools/pull/1003)
* Fix `delegateToSchema` to allow delegation to subscriptions with different root field names, allows
the use of the `RenameRootFields` transform with subscriptions,
pull request [#1104](https://github.com/apollographql/graphql-tools/pull/1104), fixes
[#997](https://github.com/apollographql/graphql-tools/issues/997). <br/>

### 4.0.4

Expand Down
7 changes: 3 additions & 4 deletions src/stitching/delegateToSchema.ts
Expand Up @@ -125,12 +125,11 @@ async function delegateToSchemaImplementation(
// "subscribe" to the subscription result and map the result through the transforms
return mapAsyncIterator<ExecutionResult, any>(executionResult, result => {
const transformedResult = applyResultTransforms(result, transforms);
const subscriptionKey = Object.keys(result.data)[0];

// for some reason the returned transformedResult needs to be nested inside the root subscription field
// does not work otherwise...
// wrap with fieldName to return for an additional round of resolutioon
// with payload as rootValue
return {
[subscriptionKey]: transformedResult,
[info.fieldName]: transformedResult,
};
});
}
Expand Down
64 changes: 62 additions & 2 deletions src/test/testAlternateMergeSchemas.ts
@@ -1,15 +1,28 @@
/* tslint:disable:no-unused-expression */

import { expect } from 'chai';
import { graphql, GraphQLSchema } from 'graphql';
import {
graphql,
GraphQLSchema,
ExecutionResult,
subscribe,
parse,
} from 'graphql';
import mergeSchemas from '../stitching/mergeSchemas';
import {
transformSchema,
FilterRootFields,
RenameTypes,
RenameRootFields,
} from '../transforms';
import { propertySchema, bookingSchema } from './testingSchemas';
import {
propertySchema,
bookingSchema,
subscriptionSchema,
subscriptionPubSub,
subscriptionPubSubTrigger,
} from './testingSchemas';
import { forAwaitEach } from 'iterall';

let linkSchema = `
"""
Expand Down Expand Up @@ -78,11 +91,23 @@ describe('merge schemas through transforms', () => {
(operation: string, name: string) => `Bookings_${name}`,
),
]);
const transformedSubscriptionSchema = transformSchema(subscriptionSchema, [
new FilterRootFields(
(operation: string, rootField: string) =>
// must include a Query type otherwise graphql will error
'Query.notifications' === `${operation}.${rootField}` ||
'Subscription.notifications' === `${operation}.${rootField}`,
),
new RenameTypes((name: string) => `Subscriptions_${name}`),
new RenameRootFields(
(operation: string, name: string) => `Subscriptions_${name}`),
]);

mergedSchema = mergeSchemas({
schemas: [
transformedPropertySchema,
transformedBookingSchema,
transformedSubscriptionSchema,
linkSchema,
],
resolvers: {
Expand Down Expand Up @@ -234,6 +259,41 @@ describe('merge schemas through transforms', () => {
},
});
});

it('local subscriptions should work even if root fields are renamed', done => {
const originalNotification = {
notifications: {
text: 'Hello world',
},
};

const transformedNotification = {
Subscriptions_notifications: originalNotification.notifications
};

const subscription = parse(`
subscription Subscription {
Subscriptions_notifications {
text
}
}
`);

let notificationCnt = 0;
subscribe(mergedSchema, subscription)
.then(results => {
forAwaitEach(
results as AsyncIterable<ExecutionResult>,
(result: ExecutionResult) => {
expect(result).to.have.property('data');
expect(result.data).to.deep.equal(transformedNotification);
!notificationCnt++ ? done() : null;
},
).catch(done);
}).then(() => {
subscriptionPubSub.publish(subscriptionPubSubTrigger, originalNotification);
}).catch(done);
});
});

describe('interface resolver inheritance', () => {
Expand Down