UNPKG

@graphql-tools/stitch

Version:

A set of utils for faster development of GraphQL tools

134 lines (133 loc) 4.94 kB
import { DirectiveLocation, getDirectiveValues, GraphQLDeprecatedDirective, GraphQLDirective, GraphQLEnumType, GraphQLInputObjectType, GraphQLInterfaceType, GraphQLObjectType, GraphQLScalarType, GraphQLUnionType, Kind, valueFromASTUntyped, } from 'graphql'; import { createNamedStub, createStub, getDescription, } from '@graphql-tools/utils'; const backcompatOptions = { commentDescriptions: true }; export default typeFromAST; function typeFromAST(node) { switch (node.kind) { case Kind.OBJECT_TYPE_DEFINITION: return makeObjectType(node); case Kind.INTERFACE_TYPE_DEFINITION: return makeInterfaceType(node); case Kind.ENUM_TYPE_DEFINITION: return makeEnumType(node); case Kind.UNION_TYPE_DEFINITION: return makeUnionType(node); case Kind.SCALAR_TYPE_DEFINITION: return makeScalarType(node); case Kind.INPUT_OBJECT_TYPE_DEFINITION: return makeInputObjectType(node); case Kind.DIRECTIVE_DEFINITION: return makeDirective(node); default: return null; } } function makeObjectType(node) { const config = { name: node.name.value, description: getDescription(node, backcompatOptions), interfaces: () => node.interfaces?.map(iface => createNamedStub(iface.name.value, 'interface')) || [], fields: () => (node.fields != null ? makeFields(node.fields) : {}), astNode: node, }; return new GraphQLObjectType(config); } function makeInterfaceType(node) { const config = { name: node.name.value, description: getDescription(node, backcompatOptions), interfaces: () => node.interfaces?.map(iface => createNamedStub(iface.name.value, 'interface')), fields: () => (node.fields != null ? makeFields(node.fields) : {}), astNode: node, }; return new GraphQLInterfaceType(config); } function makeEnumType(node) { const values = node.values?.reduce((prev, value) => ({ ...prev, [value.name.value]: { description: getDescription(value, backcompatOptions), deprecationReason: getDeprecationReason(value), astNode: value, }, }), {}) ?? {}; return new GraphQLEnumType({ name: node.name.value, description: getDescription(node, backcompatOptions), values, astNode: node, }); } function makeUnionType(node) { return new GraphQLUnionType({ name: node.name.value, description: getDescription(node, backcompatOptions), types: () => node.types?.map(type => createNamedStub(type.name.value, 'object')) ?? [], astNode: node, }); } function makeScalarType(node) { return new GraphQLScalarType({ name: node.name.value, description: getDescription(node, backcompatOptions), astNode: node, // TODO: serialize default property setting can be dropped once // upstream graphql-js TypeScript typings are updated, likely in v16 serialize: value => value, }); } function makeInputObjectType(node) { return new GraphQLInputObjectType({ name: node.name.value, description: getDescription(node, backcompatOptions), fields: () => (node.fields ? makeValues(node.fields) : {}), astNode: node, }); } function makeFields(nodes) { return nodes.reduce((prev, node) => ({ ...prev, [node.name.value]: { type: createStub(node.type, 'output'), description: getDescription(node, backcompatOptions), args: makeValues(node.arguments ?? []), deprecationReason: getDeprecationReason(node), astNode: node, }, }), {}); } function makeValues(nodes) { return nodes.reduce((prev, node) => ({ ...prev, [node.name.value]: { type: createStub(node.type, 'input'), defaultValue: node.defaultValue !== undefined ? valueFromASTUntyped(node.defaultValue) : undefined, description: getDescription(node, backcompatOptions), astNode: node, }, }), {}); } function isLocationValue(value) { return value in DirectiveLocation; } function makeDirective(node) { const locations = []; for (const location of node.locations) { const locationValue = location.value; if (isLocationValue(locationValue)) { locations.push(locationValue); } } return new GraphQLDirective({ name: node.name.value, description: node.description != null ? node.description.value : null, locations: locations, isRepeatable: node.repeatable, args: makeValues(node.arguments ?? []), astNode: node, }); } function getDeprecationReason(node) { const deprecated = getDirectiveValues(GraphQLDeprecatedDirective, node); return deprecated?.['reason']; }