diff --git a/.changeset/chilled-trees-act.md b/.changeset/chilled-trees-act.md new file mode 100644 index 00000000000..389542b4f79 --- /dev/null +++ b/.changeset/chilled-trees-act.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +--- + +remove broken isTypeOf call for expanding fragments with flattenGeneratedTypes = true diff --git a/.changeset/nasty-dragons-turn.md b/.changeset/nasty-dragons-turn.md new file mode 100644 index 00000000000..f5aff2ea541 --- /dev/null +++ b/.changeset/nasty-dragons-turn.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/typescript-operations': patch +'@graphql-codegen/flow-operations': patch +--- + +Remove broken isTypeOf call (always undefined in graphql-tools v6) diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index c2d54db6738..a9d6530df0f 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -102,7 +102,7 @@ export class SelectionSetToObject = T | null; +export type Exact = { [K in keyof T]: T[K] }; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; +}; + +export type Query = { + __typename?: 'Query'; + search?: Maybe>; +}; + +export type Concept = { + id?: Maybe; +}; + +export type Dimension = Concept & { + __typename?: 'Dimension'; + id?: Maybe; +}; + +export type DimValue = { + __typename?: 'DimValue'; + dimension?: Maybe; + value: Scalars['String']; +}; + +export type Searchable = Dimension | DimValue; +export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; + + +export type SearchPopularQuery = ( + { __typename?: 'Query' } + & { search?: Maybe + ) | ( + { __typename?: 'DimValue' } + & Pick + & { dimension?: Maybe<( + { __typename?: 'Dimension' } + & Pick + )> } + )>> } +); +" +`; + exports[`TypeScript Operations Plugin Union & Interfaces Should handle union selection sets with both FragmentSpreads and InlineFragments 1`] = ` "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 3f3f9afefb6..d2fe21cd218 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -3593,6 +3593,119 @@ describe('TypeScript Operations Plugin', () => { `); }); + it('#4216 - handle fragments against unions and interfaces with flattenGeneratedTypes', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + schema { + query: Query + } + + type Query { + search: [Searchable!] + } + + interface Concept { + id: String + } + + type Dimension implements Concept { + id: String + } + + type DimValue { + dimension: Dimension + value: String! + } + + union Searchable = Dimension | DimValue + `); + + const query = parse(/* GraphQL */ ` + query SearchPopular { + search { + ...SearchableFragment + } + } + + fragment SearchableFragment on Searchable { + ...SearchConceptFragment + ...SearchDimValueFragment + } + + fragment SearchConceptFragment on Concept { + id + } + + fragment SearchDimValueFragment on DimValue { + dimension { + ...SearchConceptFragment + } + value + } + `); + + const config = { + flattenGeneratedTypes: true, + }; + + const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { + outputFile: 'graphql.ts', + }); + + const output = await validate(content, config, testSchema); + expect(mergeOutputs([output])).toMatchSnapshot(); + + expect(output).toBeSimilarStringTo(` + export type Maybe = T | null; + export type Exact = { [K in keyof T]: T[K] }; + /** All built-in and custom scalars, mapped to their actual values */ + export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; + }; + + export type Query = { + __typename?: 'Query'; + search?: Maybe>; + }; + + export type Concept = { + id?: Maybe; + }; + + export type Dimension = Concept & { + __typename?: 'Dimension'; + id?: Maybe; + }; + + export type DimValue = { + __typename?: 'DimValue'; + dimension?: Maybe; + value: Scalars['String']; + }; + + export type Searchable = Dimension | DimValue; + export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; + + + export type SearchPopularQuery = ( + { __typename?: 'Query' } + & { search?: Maybe + ) | ( + { __typename?: 'DimValue' } + & Pick + & { dimension?: Maybe<( + { __typename?: 'Dimension' } + & Pick + )> } + )>> } + );`); + }); + it('Should add operation name when addOperationExport is true', async () => { const testSchema = buildSchema(/* GraphQL */ ` type User { @@ -3788,6 +3901,49 @@ describe('TypeScript Operations Plugin', () => { }); describe('Issues', () => { + it('#4389 - validate issues with interfaces', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + interface A { + a: String! + } + + interface B implements A { + a: String! + b: String + } + + type C implements B { + a: String! + b: String + c: String! + } + + type Query { + foo: C + } + `); + + const query = parse(/* GraphQL */ ` + query { + foo { + ... on A { + a + } + } + } + `); + + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + {}, + { + outputFile: 'graphql.ts', + } + ); + expect(content).toContain(`{ foo?: Maybe<{ __typename?: 'C' }> }`); + }); + it('#5001 - incorrect output with typeSuffix', async () => { const testSchema = buildSchema(/* GraphQL */ ` type Query {