From 2e9333849d8f5a4a0d360f7e72db60bfba27e7ba Mon Sep 17 00:00:00 2001 From: Tim Griesser Date: Thu, 5 Nov 2020 13:12:13 -0500 Subject: [PATCH] fix: deduplicate interfaces implementing interfaces (#608) --- src/builder.ts | 2 +- .../__snapshots__/interfaceType.spec.ts.snap | 25 ++++++++++++++ tests/interfaceType.spec.ts | 34 ++++++++++++++++++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/builder.ts b/src/builder.ts index 50df9a3e..e7b46ef1 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -1055,7 +1055,7 @@ export class SchemaBuilder { const type = this.getInterface(i) list.push(type, ...type.getInterfaces()) }) - return list + return Array.from(new Set(list)) } protected buildInterfaceFields(interfaces: (string | NexusInterfaceTypeDef)[]) { diff --git a/tests/__snapshots__/interfaceType.spec.ts.snap b/tests/__snapshots__/interfaceType.spec.ts.snap index 5aeb94b6..3a3a0552 100644 --- a/tests/__snapshots__/interfaceType.spec.ts.snap +++ b/tests/__snapshots__/interfaceType.spec.ts.snap @@ -26,6 +26,31 @@ Object { exports[`interfaceType can not implement itself 1`] = `"GraphQL Nexus: Interface Node can't implement itself"`; +exports[`interfaceType deduplicates interfaces implementing interfaces 1`] = ` +"### This file was generated by Nexus Schema +### Do not make changes to this file directly + + +interface Node { + id: ID +} + +interface Node2 implements Node { + id: ID + id2: ID +} + +type Foo implements Node2 & Node { + id: ID + id2: ID +} + +type Query { + ok: Boolean! +} +" +`; + exports[`interfaceType detects circular dependencies 1`] = `"GraphQL Nexus: Interface circular dependency detected NodeA -> NodeC -> NodeB -> NodeA"`; exports[`interfaceType logs error when resolveType is not provided for an interface 1`] = ` diff --git a/tests/interfaceType.spec.ts b/tests/interfaceType.spec.ts index 43752b6a..fe3a8fd3 100644 --- a/tests/interfaceType.spec.ts +++ b/tests/interfaceType.spec.ts @@ -1,6 +1,6 @@ import { graphql } from 'graphql' import path from 'path' -import { interfaceType, makeSchema, objectType, queryField } from '../src/core' +import { interfaceType, makeSchema, objectType, queryField, generateSchema } from '../src/core' describe('interfaceType', () => { it('can be implemented by object types', async () => { @@ -127,6 +127,38 @@ describe('interfaceType', () => { }) ).toThrowErrorMatchingSnapshot() }) + it('deduplicates interfaces implementing interfaces', async () => { + const { schemaTypes } = await generateSchema.withArtifacts( + { + types: [ + interfaceType({ + name: 'Node', + definition(t) { + t.id('id') + t.resolveType(() => null) + }, + }), + interfaceType({ + name: 'Node2', + definition(t) { + t.implements('Node') + t.id('id2') + t.resolveType(() => null) + }, + }), + objectType({ + name: 'Foo', + definition(t) { + t.implements('Node2', 'Node') + }, + }), + ], + outputs: false, + }, + false + ) + expect(schemaTypes).toMatchSnapshot() + }) it('detects circular dependencies', async () => { expect(() => makeSchema({