|
1 | | -import { Kind, TypeNode } from "graphql/index"; |
2 | | -import { GraphQLSchema, TypeDefinitionNode } from "graphql"; |
| 1 | +import { |
| 2 | + GraphQLSchema, |
| 3 | + InputObjectTypeDefinitionNode, |
| 4 | + isInputObjectType, |
| 5 | + isObjectType, |
| 6 | +} from "graphql"; |
| 7 | +import { getBaseTypeNode } from "@graphql-codegen/visitor-plugin-common"; |
3 | 8 |
|
4 | 9 | export function inputTypeHasMatchingOutputType( |
| 10 | + inputNode: InputObjectTypeDefinitionNode, |
5 | 11 | schema: GraphQLSchema, |
6 | | - typeNode?: TypeDefinitionNode | null, |
7 | 12 | ) { |
8 | | - if (typeNode?.kind !== Kind.INPUT_OBJECT_TYPE_DEFINITION) { |
9 | | - return false; |
10 | | - } |
11 | | - |
12 | | - const typeNameWithoutInput = getTypeNameWithoutInput(typeNode.name.value); |
13 | | - const matchingType = schema.getType(typeNameWithoutInput)?.astNode; |
14 | | - const matchingTypeFields = |
15 | | - matchingType?.kind === Kind.OBJECT_TYPE_DEFINITION |
16 | | - ? matchingType.fields |
17 | | - : []; |
18 | | - const inputFields = typeNode.fields; |
19 | | - const fieldsMatch = matchingTypeFields?.every((field) => { |
20 | | - const matchingInputField = inputFields?.find( |
21 | | - (inputField) => inputField.name.value === field.name.value, |
22 | | - ); |
23 | | - if (!matchingInputField) return false; |
24 | | - return fieldsAreEquivalent(field.type, matchingInputField.type); |
25 | | - }); |
26 | | - return Boolean(matchingTypeFields?.length && fieldsMatch); |
| 13 | + const inputName = inputNode.name.value; |
| 14 | + const typeNameWithoutInput = getTypeNameWithoutInput(inputName); |
| 15 | + const matchingTypeName = |
| 16 | + schema.getType(typeNameWithoutInput)?.astNode?.name.value; |
| 17 | + return Boolean( |
| 18 | + matchingTypeName && typesAreEquivalent(matchingTypeName, inputName, schema), |
| 19 | + ); |
27 | 20 | } |
28 | 21 |
|
29 | 22 | export function getTypeNameWithoutInput(name: string) { |
30 | 23 | return name.endsWith("Input") ? name.replace("Input", "") : name; |
31 | 24 | } |
32 | 25 |
|
33 | | -function fieldsAreEquivalent( |
34 | | - typeField: TypeNode, |
35 | | - inputField: TypeNode, |
| 26 | +function typesAreEquivalent( |
| 27 | + typeName: string, |
| 28 | + inputName: string, |
| 29 | + schema: GraphQLSchema, |
36 | 30 | ): boolean { |
37 | | - switch (typeField.kind) { |
38 | | - case Kind.NAMED_TYPE: |
39 | | - return ( |
40 | | - inputField.kind === Kind.NAMED_TYPE && |
41 | | - typeField.name.value === getTypeNameWithoutInput(inputField.name.value) |
42 | | - ); |
43 | | - case Kind.LIST_TYPE: |
44 | | - return ( |
45 | | - inputField.kind === Kind.LIST_TYPE && |
46 | | - fieldsAreEquivalent(typeField.type, inputField.type) |
47 | | - ); |
48 | | - case Kind.NON_NULL_TYPE: |
49 | | - return ( |
50 | | - inputField.kind === Kind.NON_NULL_TYPE && |
51 | | - fieldsAreEquivalent(typeField.type, inputField.type) |
52 | | - ); |
| 31 | + const typeNode = schema.getType(typeName); |
| 32 | + const inputNode = schema.getType(inputName); |
| 33 | + if (!typeNode?.astNode && !inputNode?.astNode) { |
| 34 | + return true; |
53 | 35 | } |
| 36 | + if ( |
| 37 | + !isObjectType(typeNode) || |
| 38 | + !isInputObjectType(inputNode) || |
| 39 | + !typeNode.astNode?.fields || |
| 40 | + !inputNode.astNode?.fields || |
| 41 | + typeNode.astNode.fields.length !== inputNode.astNode.fields.length |
| 42 | + ) { |
| 43 | + return false; |
| 44 | + } |
| 45 | + |
| 46 | + return typeNode.astNode.fields.every((typeField) => { |
| 47 | + const matchingInputField = inputNode.astNode?.fields?.find( |
| 48 | + (inputField) => inputField.name.value === typeField.name.value, |
| 49 | + ); |
| 50 | + if (!matchingInputField?.type) return false; |
| 51 | + const baseTypeName = getBaseTypeNode(typeField.type).name.value; |
| 52 | + const baseInputTypeName = getBaseTypeNode(matchingInputField.type).name |
| 53 | + .value; |
| 54 | + const typeNamesAreEquivalent = |
| 55 | + baseTypeName == getTypeNameWithoutInput(baseInputTypeName); |
| 56 | + if (!typeNamesAreEquivalent) { |
| 57 | + return false; |
| 58 | + } |
| 59 | + return typesAreEquivalent(baseTypeName, baseInputTypeName, schema); |
| 60 | + }); |
54 | 61 | } |
0 commit comments