From 12277ba9861536a7a0fb83775088ee78e30ce7e7 Mon Sep 17 00:00:00 2001 From: yaacovCR Date: Mon, 6 Jan 2020 12:38:45 -0500 Subject: [PATCH] chore(upstream): graphql v15 support - add code support for interfaces that implement interfaces - changes one implementation within tests to implement the interface implementer :) - removes some verbose tests to make the above changes more facile - do not call extendSchema after buildSchema as both now process extensions - use getIntrospectionQuery method instead of introspectionQuery object - type/lint changes --- .travis.yml | 3 +- package.json | 4 +- .../buildSchemaFromTypeDefinitions.ts | 8 - src/stitching/introspectSchema.ts | 4 +- src/stitching/typeFromAST.ts | 4 + src/test/testAlternateMergeSchemas.ts | 199 +----------------- src/test/testSchemaGenerator.ts | 2 +- src/test/testingSchemas.ts | 7 +- src/utils/clone.ts | 6 +- src/utils/heal.ts | 9 +- 10 files changed, 26 insertions(+), 220 deletions(-) diff --git a/.travis.yml b/.travis.yml index 99171bb7f88..6c54fef6f63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ install: - npm install -g mocha coveralls - npm install - npm install graphql@$GRAPHQL_VERSION - - npm install @types/graphql@$TYPES_GRAPHQL_VERSION script: - npm test @@ -20,4 +19,4 @@ script: sudo: false env: - - GRAPHQL_VERSION='^14.0' TYPES_GRAPHQL_VERSION='^14.0' + - GRAPHQL_VERSION='^15.0.0-rc.1' diff --git a/package.json b/package.json index 79ae130c667..abe677171ae 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "uuid": "^3.3.3" }, "peerDependencies": { - "graphql": "^14.2.0" + "graphql": "^15.0.0-rc.1" }, "devDependencies": { "@types/apollo-upload-client": "^8.1.3", @@ -82,7 +82,7 @@ "dateformat": "^3.0.3", "express": "^4.17.1", "express-graphql": "^0.9.0", - "graphql": "^14.5.8", + "graphql": "^15.0.0-rc.1", "graphql-subscriptions": "^1.1.0", "graphql-type-json": "^0.3.1", "graphql-upload": "^9.0.0", diff --git a/src/generate/buildSchemaFromTypeDefinitions.ts b/src/generate/buildSchemaFromTypeDefinitions.ts index fbc52a859b4..aee9f6e1211 100644 --- a/src/generate/buildSchemaFromTypeDefinitions.ts +++ b/src/generate/buildSchemaFromTypeDefinitions.ts @@ -1,13 +1,11 @@ import { parse, - extendSchema, buildASTSchema, GraphQLSchema, DocumentNode, } from 'graphql'; import { ITypeDefinitions, GraphQLParseOptions } from '../Interfaces'; -import extractExtensionDefinitions from './extractExtensionDefinitions'; import concatenateTypeDefs from './concatenateTypeDefs'; import SchemaError from './SchemaError'; @@ -43,12 +41,6 @@ function buildSchemaFromTypeDefinitions( backcompatOptions, ); - const extensionsAst = extractExtensionDefinitions(astDocument); - if (extensionsAst.definitions.length > 0) { - // TODO fix types https://github.com/apollographql/graphql-tools/issues/542 - schema = (extendSchema as any)(schema, extensionsAst, backcompatOptions); - } - return schema; } diff --git a/src/stitching/introspectSchema.ts b/src/stitching/introspectSchema.ts index 0e2877138fc..304ac2144ad 100644 --- a/src/stitching/introspectSchema.ts +++ b/src/stitching/introspectSchema.ts @@ -1,10 +1,10 @@ import { GraphQLSchema, DocumentNode } from 'graphql'; -import { introspectionQuery, buildClientSchema, parse } from 'graphql'; +import { getIntrospectionQuery, buildClientSchema, parse } from 'graphql'; import { ApolloLink } from 'apollo-link'; import { Fetcher } from '../Interfaces'; import linkToFetcher from './linkToFetcher'; -const parsedIntrospectionQuery: DocumentNode = parse(introspectionQuery); +const parsedIntrospectionQuery: DocumentNode = parse(getIntrospectionQuery()); export default async function introspectSchema( fetcher: ApolloLink | Fetcher, diff --git a/src/stitching/typeFromAST.ts b/src/stitching/typeFromAST.ts index d76f99a5d5e..2d1742bc33d 100644 --- a/src/stitching/typeFromAST.ts +++ b/src/stitching/typeFromAST.ts @@ -83,6 +83,10 @@ function makeInterfaceType( return new GraphQLInterfaceType({ name: node.name.value, fields: () => makeFields(node.fields), + interfaces: () => + node.interfaces.map( + iface => createNamedStub(iface.name.value, 'interface') as GraphQLInterfaceType, + ), description: getDescription(node, backcompatOptions), resolveType: parent => resolveFromParentTypename(parent), }); diff --git a/src/test/testAlternateMergeSchemas.ts b/src/test/testAlternateMergeSchemas.ts index d082f1ff4d3..a0a43c81af0 100644 --- a/src/test/testAlternateMergeSchemas.ts +++ b/src/test/testAlternateMergeSchemas.ts @@ -614,98 +614,11 @@ type Query { }); describe('WrapType transform', () => { - let transformedPropertySchema: GraphQLSchema; - - before(async () => { - transformedPropertySchema = transformSchema(propertySchema, [ + it('should work', async () => { + const transformedPropertySchema = transformSchema(propertySchema, [ new WrapType('Query', 'Namespace_Query', 'namespace'), ]); - }); - - it('should modify the schema', () => { - /* tslint:disable:max-line-length */ - expect(printSchema(transformedPropertySchema)).to.equal(`type Address { - street: String - city: String - state: String - zip: String -} - -"""Simple fake datetime""" -scalar DateTime - -input InputWithDefault { - test: String = "Foo" -} -""" -The \`JSON\` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). -""" -scalar JSON - -type Location { - name: String! -} - -type Namespace_Query { - propertyById(id: ID!): Property - properties(limit: Int): [Property!] - contextTest(key: String!): String - dateTimeTest: DateTime - jsonTest(input: JSON): JSON - interfaceTest(kind: TestInterfaceKind): TestInterface - unionTest(output: String): TestUnion - errorTest: String - errorTestNonNull: String! - relay: Query! - defaultInputTest(input: InputWithDefault!): String -} - -type Property { - id: ID! - name: String! - location: Location - address: Address - error: String -} - -type Query { - namespace: Namespace_Query -} - -type TestImpl1 implements TestInterface { - kind: TestInterfaceKind - testString: String - foo: String -} - -type TestImpl2 implements TestInterface { - kind: TestInterfaceKind - testString: String - bar: String -} - -interface TestInterface { - kind: TestInterfaceKind - testString: String -} - -enum TestInterfaceKind { - ONE - TWO -} - -union TestUnion = TestImpl1 | UnionImpl - -type UnionImpl { - someField: String -} -` - /* tslint:enable:max-line-length */ - ); - }); - - it('should work', async () => { const result = await graphql( transformedPropertySchema, ` @@ -759,114 +672,6 @@ type UnionImpl { }); }); -describe('ExtendSchema transform', () => { - let transformedPropertySchema: GraphQLSchema; - - before(async () => { - transformedPropertySchema = transformSchema(propertySchema, [ - new ExtendSchema({ - typeDefs: ` - extend type Property { - locationName: String - wrap: Wrap - } - - type Wrap { - id: ID - name: String - } - `, - }), - ]); - }); - - it('should work', () => { - /* tslint:disable:max-line-length */ - expect(printSchema(transformedPropertySchema)).to.equal(`type Address { - street: String - city: String - state: String - zip: String -} - -"""Simple fake datetime""" -scalar DateTime - -input InputWithDefault { - test: String = "Foo" -} - -""" -The \`JSON\` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). -""" -scalar JSON - -type Location { - name: String! -} - -type Property { - id: ID! - name: String! - location: Location - address: Address - error: String - locationName: String - wrap: Wrap -} - -type Query { - propertyById(id: ID!): Property - properties(limit: Int): [Property!] - contextTest(key: String!): String - dateTimeTest: DateTime - jsonTest(input: JSON): JSON - interfaceTest(kind: TestInterfaceKind): TestInterface - unionTest(output: String): TestUnion - errorTest: String - errorTestNonNull: String! - relay: Query! - defaultInputTest(input: InputWithDefault!): String -} - -type TestImpl1 implements TestInterface { - kind: TestInterfaceKind - testString: String - foo: String -} - -type TestImpl2 implements TestInterface { - kind: TestInterfaceKind - testString: String - bar: String -} - -interface TestInterface { - kind: TestInterfaceKind - testString: String -} - -enum TestInterfaceKind { - ONE - TWO -} - -union TestUnion = TestImpl1 | UnionImpl - -type UnionImpl { - someField: String -} - -type Wrap { - id: ID - name: String -} -` - /* tslint:enable:max-line-length */ - ); - }); -}); - describe('schema transformation with extraction of nested fields', () => { it('should work via ExtendSchema transform', async () => { const transformedPropertySchema = transformSchema(propertySchema, [ diff --git a/src/test/testSchemaGenerator.ts b/src/test/testSchemaGenerator.ts index 6d395996bce..c7afb71ad38 100644 --- a/src/test/testSchemaGenerator.ts +++ b/src/test/testSchemaGenerator.ts @@ -248,7 +248,7 @@ describe('generating schema from shorthand', () => { }, query: { name: 'RootQuery', - description: '', + description: null, fields: [ { name: 'species', diff --git a/src/test/testingSchemas.ts b/src/test/testingSchemas.ts index 4d24f36f957..d38467bb39f 100644 --- a/src/test/testingSchemas.ts +++ b/src/test/testingSchemas.ts @@ -276,7 +276,12 @@ const propertyRootTypeDefs = ` foo: String } - type TestImpl2 implements TestInterface { + interface TestNestedInterface implements TestInterface { + kind: TestInterfaceKind + testString: String + } + + type TestImpl2 implements TestNestedInterface & TestInterface { kind: TestInterfaceKind testString: String bar: String diff --git a/src/utils/clone.ts b/src/utils/clone.ts index fd34ea98ae8..dbda73619b7 100644 --- a/src/utils/clone.ts +++ b/src/utils/clone.ts @@ -24,7 +24,11 @@ export function cloneType(type: GraphQLNamedType): GraphQLNamedType { interfaces: config.interfaces.slice(), }); } else if (type instanceof GraphQLInterfaceType) { - return new GraphQLInterfaceType(type.toConfig()); + const config = type.toConfig(); + return new GraphQLInterfaceType({ + ...config, + interfaces: config.interfaces.slice(), + }); } else if (type instanceof GraphQLUnionType) { const config = type.toConfig(); return new GraphQLUnionType({ diff --git a/src/utils/heal.ts b/src/utils/heal.ts index 63d68a48bd8..1f9ff6dcac3 100644 --- a/src/utils/heal.ts +++ b/src/utils/heal.ts @@ -111,13 +111,10 @@ export function healTypes( } function heal(type: VisitableSchemaType) { - if (type instanceof GraphQLObjectType) { + if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) { healFields(type); healInterfaces(type); - } else if (type instanceof GraphQLInterfaceType) { - healFields(type); - } else if (type instanceof GraphQLUnionType) { healUnderlyingTypes(type); @@ -145,7 +142,7 @@ export function healTypes( }); } - function healInterfaces(type: GraphQLObjectType) { + function healInterfaces(type: GraphQLObjectType | GraphQLInterfaceType) { updateEachKey(type.getInterfaces(), iface => { const healedType = healType(iface); return healedType; @@ -200,7 +197,7 @@ export function healTypes( function pruneTypes(typeMap: NamedTypeMap, directives: ReadonlyArray) { const implementedInterfaces = {}; each(typeMap, (namedType, typeName) => { - if (namedType instanceof GraphQLObjectType) { + if (namedType instanceof GraphQLObjectType || namedType instanceof GraphQLInterfaceType) { each(namedType.getInterfaces(), iface => { implementedInterfaces[iface.name] = true; });