Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
at main 95 lines 2.2 kB view raw
1import type { 2 SelectionNode, 3 ASTNode, 4 DefinitionNode, 5 GraphQLSchema, 6 GraphQLFieldMap, 7 FragmentDefinitionNode, 8 FragmentSpreadNode, 9} from 'graphql'; 10import { Kind, isAbstractType } from 'graphql'; 11import { unwrapType, getName } from './node'; 12 13export function traverse( 14 node: ASTNode, 15 enter?: (n: ASTNode) => ASTNode | void, 16 exit?: (n: ASTNode) => ASTNode | void 17): any { 18 if (enter) { 19 node = enter(node) || node; 20 } 21 22 switch (node.kind) { 23 case Kind.DOCUMENT: { 24 node = { 25 ...node, 26 definitions: node.definitions.map( 27 n => traverse(n, enter, exit) as DefinitionNode 28 ), 29 }; 30 break; 31 } 32 case Kind.OPERATION_DEFINITION: 33 case Kind.FIELD: 34 case Kind.FRAGMENT_DEFINITION: { 35 if (node.selectionSet) { 36 node = { 37 ...node, 38 selectionSet: { 39 ...node.selectionSet, 40 selections: node.selectionSet.selections.map( 41 n => traverse(n, enter, exit) as SelectionNode 42 ), 43 }, 44 }; 45 } 46 break; 47 } 48 } 49 50 if (exit) { 51 node = exit(node) || node; 52 } 53 54 return node; 55} 56 57export function resolveFields( 58 schema: GraphQLSchema, 59 visits: string[] 60): GraphQLFieldMap<any, any> { 61 let currentFields = schema.getQueryType()!.getFields(); 62 63 for (let i = 0; i < visits.length; i++) { 64 const t = unwrapType(currentFields[visits[i]].type); 65 66 if (isAbstractType(t)) { 67 currentFields = {}; 68 schema.getPossibleTypes(t).forEach(implementedType => { 69 currentFields = { 70 ...currentFields, 71 // @ts-ignore TODO: proper casting 72 ...schema.getType(implementedType.name)!.toConfig().fields, 73 }; 74 }); 75 } else { 76 // @ts-ignore TODO: proper casting 77 currentFields = schema.getType(t!.name)!.toConfig().fields; 78 } 79 } 80 81 return currentFields; 82} 83 84/** Get fragment names referenced by node. */ 85export function getUsedFragmentNames(node: FragmentDefinitionNode) { 86 const names: string[] = []; 87 88 traverse(node, n => { 89 if (n.kind === Kind.FRAGMENT_SPREAD) { 90 names.push(getName(n as FragmentSpreadNode)); 91 } 92 }); 93 94 return names; 95}