Skip to content
This repository has been archived by the owner on Apr 15, 2020. It is now read-only.

Commit

Permalink
feat(generate): Allow user-provided buildSchema options (ardatan#1154)
Browse files Browse the repository at this point in the history
* Allow buildSchema options to be passed in by the user

* Add congruency for printSchema options

* Prettier

* Add tests for new buildSchema options
  • Loading branch information
trevor-scheer authored and yaacovCR committed Jun 28, 2019
1 parent ea0d359 commit 829255e
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 45 deletions.
17 changes: 11 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,24 @@ Previously, the merged schema internally used the serialized version.


## [5.0.0](https://github.com/yaacovCR/graphql-tools-fork/compare/v4.0.4...v5.0.0) (2019-06-02)

* Fixes a bug where schemas with scalars could not be merged when passed to
`mergeSchemas` as a string or `GraphQLSchema`. <br/>
[@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)
* First forked version, bumped major version despite lack of breaking changes.
* 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/>
* Add transformers to rename, filter, and arbitrarily transform object fields. <br/>
Fixes [#819](https://github.com/apollographql/graphql-tools/issues/819).

### 4.0.5

* Fixes a bug where schemas with scalars could not be merged when passed to
`mergeSchemas` as a string or `GraphQLSchema`. <br/>
[@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)
* Allow user-provided `buildSchema` options. <br/>
[@trevor-scheer](https://github.com/trevor-scheer) in [#1154](https://github.com/apollographql/graphql-tools/pull/1154)

### 4.0.4

* Make `WrapQuery` work for non-root fields <br />
Expand Down
58 changes: 24 additions & 34 deletions src/stitching/makeRemoteExecutableSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
printSchema,
Kind,
GraphQLResolveInfo,
DocumentNode
DocumentNode,
BuildSchemaOptions
} from 'graphql';
import linkToFetcher, { execute } from './linkToFetcher';
import isEmptyObject from '../isEmptyObject';
Expand All @@ -30,12 +31,13 @@ import resolveParentFromTypename from './resolveFromParentTypename';
import defaultMergedResolver from './defaultMergedResolver';
import { checkResultAndHandleErrors } from './checkResultAndHandleErrors';
import { observableToAsyncIterable } from './observableToAsyncIterable';
import { Options as PrintSchemaOptions } from 'graphql/utilities/schemaPrinter';

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

export type Fetcher = (operation: FetcherOperation) => Promise<ExecutionResult>;
Expand All @@ -51,26 +53,28 @@ export default function makeRemoteExecutableSchema({
schema,
link,
fetcher,
createResolver: customCreateResolver = createResolver
createResolver: customCreateResolver = createResolver,
buildSchemaOptions,
printSchemaOptions = { commentDescriptions: true }
}: {
schema: GraphQLSchema | string;
link?: ApolloLink;
fetcher?: Fetcher;
createResolver?: (fetcher: Fetcher) => GraphQLFieldResolver<any, any>
createResolver?: (fetcher: Fetcher) => GraphQLFieldResolver<any, any>;
buildSchemaOptions?: BuildSchemaOptions;
printSchemaOptions?: PrintSchemaOptions;
}): GraphQLSchema {
if (!fetcher && link) {
fetcher = linkToFetcher(link);
}

let typeDefs: string;
const printOptions = { commentDescriptions: true };

if (typeof schema === 'string') {
typeDefs = schema;
schema = buildSchema(typeDefs);
schema = buildSchema(typeDefs, buildSchemaOptions);
} else {
// TODO fix types https://github.com/apollographql/graphql-tools/issues/542
typeDefs = (printSchema as any)(schema, printOptions);
typeDefs = printSchema(schema, printSchemaOptions);
}

// prepare query resolvers
Expand Down Expand Up @@ -98,7 +102,7 @@ export default function makeRemoteExecutableSchema({
const subscriptions = subscriptionType.getFields();
Object.keys(subscriptions).forEach(key => {
subscriptionResolvers[key] = {
subscribe: createSubscriptionResolver(key, link),
subscribe: createSubscriptionResolver(key, link)
};
});
}
Expand All @@ -118,14 +122,11 @@ export default function makeRemoteExecutableSchema({
const typeMap = schema.getTypeMap();
const types = Object.keys(typeMap).map(name => typeMap[name]);
for (const type of types) {
if (
type instanceof GraphQLInterfaceType ||
type instanceof GraphQLUnionType
) {
if (type instanceof GraphQLInterfaceType || type instanceof GraphQLUnionType) {
resolvers[type.name] = {
__resolveType(parent, context, info) {
return resolveParentFromTypename(parent, info.schema);
},
}
};
} else if (type instanceof GraphQLScalarType) {
if (
Expand All @@ -137,11 +138,7 @@ export default function makeRemoteExecutableSchema({
type === GraphQLInt
)
) {
resolvers[type.name] = recreateType(
type,
(name: string) => null,
false,
) as GraphQLScalarType;
resolvers[type.name] = recreateType(type, (name: string) => null, false) as GraphQLScalarType;
}
} else if (
type instanceof GraphQLObjectType &&
Expand All @@ -160,45 +157,38 @@ export default function makeRemoteExecutableSchema({

return makeExecutableSchema({
typeDefs,
resolvers,
resolvers
});
}

export function createResolver(fetcher: Fetcher): GraphQLFieldResolver<any, any> {
return async (root, args, context, info) => {
const fragments = Object.keys(info.fragments).map(
fragment => info.fragments[fragment],
);
const fragments = Object.keys(info.fragments).map(fragment => info.fragments[fragment]);
const document = {
kind: Kind.DOCUMENT,
definitions: [info.operation, ...fragments],
definitions: [info.operation, ...fragments]
};
const result = await fetcher({
query: document,
variables: info.variableValues,
context: { graphqlContext: context },
context: { graphqlContext: context }
});
return checkResultAndHandleErrors(result, info);
};
}

function createSubscriptionResolver(
name: string,
link: ApolloLink,
): ResolverFn {
function createSubscriptionResolver(name: string, link: ApolloLink): ResolverFn {
return (root, args, context, info) => {
const fragments = Object.keys(info.fragments).map(
fragment => info.fragments[fragment],
);
const fragments = Object.keys(info.fragments).map(fragment => info.fragments[fragment]);
const document = {
kind: Kind.DOCUMENT,
definitions: [info.operation, ...fragments],
definitions: [info.operation, ...fragments]
};

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

const observable = execute(link, operation);
Expand Down
42 changes: 37 additions & 5 deletions src/test/testMakeRemoteExecutableSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
subscriptionSchema,
subscriptionPubSubTrigger,
subscriptionPubSub,
makeSchemaRemoteFromLink,
makeSchemaRemoteFromLink
} from '../test/testingSchemas';
import { makeRemoteExecutableSchema } from '../stitching';

describe('remote subscriptions', () => {
let schema: GraphQLSchema;
Expand All @@ -19,8 +20,8 @@ describe('remote subscriptions', () => {
it('should work', done => {
const mockNotification = {
notifications: {
text: 'Hello world',
},
text: 'Hello world'
}
};

const subscription = parse(`
Expand All @@ -46,8 +47,8 @@ describe('remote subscriptions', () => {
it('should work without triggering multiple times per notification', done => {
const mockNotification = {
notifications: {
text: 'Hello world',
},
text: 'Hello world'
}
};

const subscription = parse(`
Expand Down Expand Up @@ -85,3 +86,34 @@ describe('remote subscriptions', () => {
});
});
});

describe('respects buildSchema options', () => {
const schema = `
type Query {
# Field description
custom: CustomScalar!
}
# Scalar description
scalar CustomScalar
`;

it('without comment descriptions', () => {
const remoteSchema = makeRemoteExecutableSchema({ schema });

const customScalar = remoteSchema.getType('CustomScalar');
expect(customScalar.description).to.eq(undefined);
});

it('with comment descriptions', () => {
const remoteSchema = makeRemoteExecutableSchema({
schema,
buildSchemaOptions: { commentDescriptions: true }
});

const field = remoteSchema.getQueryType().getFields()['custom'];
expect(field.description).to.eq('Field description');
const customScalar = remoteSchema.getType('CustomScalar');
expect(customScalar.description).to.eq('Scalar description');
});
});

0 comments on commit 829255e

Please sign in to comment.