UNPKG

graphql-binding

Version:

[![CircleCI](https://circleci.com/gh/graphql-binding/graphql-binding.svg?style=shield)](https://circleci.com/gh/graphql-binding/graphql-binding) [![npm version](https://badge.fury.io/js/graphql-binding.svg)](https://badge.fury.io/js/graphql-binding)

205 lines 7.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var graphql_1 = require("graphql"); var utils_1 = require("./utils"); var addFragmentToInfo_1 = require("./utils/addFragmentToInfo"); function buildInfo(rootFieldName, operation, schema, info) { if (!info) { info = buildInfoForAllScalars(rootFieldName, schema, operation); } else if (info.kind && info.kind === 'Document') { info = graphql_1.print(info); } if (typeof info === 'string') { info = buildInfoFromFragment(rootFieldName, schema, operation, info); } return info; } exports.buildInfo = buildInfo; function buildInfoForAllScalars(rootFieldName, schema, operation) { var fieldNodes = []; var type = utils_1.getTypeForRootFieldName(rootFieldName, operation, schema); var namedType = graphql_1.getNamedType(type); var selections; if (graphql_1.isInterfaceType(namedType) || graphql_1.isObjectType(namedType)) { var fields_1 = namedType.getFields(); selections = Object.keys(fields_1) .filter(function (f) { return utils_1.isScalar(fields_1[f].type); }) .map(function (fieldName) { var field = fields_1[fieldName]; return { kind: 'Field', name: { kind: 'Name', value: field.name }, }; }); } var fieldNode = { kind: 'Field', name: { kind: 'Name', value: rootFieldName }, selectionSet: selections ? { kind: 'SelectionSet', selections: selections } : undefined, }; fieldNodes.push(fieldNode); var parentType = { query: function () { return schema.getQueryType(); }, mutation: function () { return schema.getMutationType(); }, subscription: function () { return schema.getSubscriptionType(); }, }[operation]() || undefined; return { fieldNodes: fieldNodes, fragments: {}, schema: schema, fieldName: rootFieldName, returnType: type, parentType: parentType, path: undefined, rootValue: undefined, operation: { kind: 'OperationDefinition', operation: operation, selectionSet: { kind: 'SelectionSet', selections: [] }, variableDefinitions: [], }, variableValues: {}, }; } exports.buildInfoForAllScalars = buildInfoForAllScalars; function buildInfoFromFragment(rootFieldName, schema, operation, query) { var type = utils_1.getTypeForRootFieldName(rootFieldName, operation, schema); var namedType = graphql_1.getNamedType(type); var fieldNode = { kind: 'Field', name: { kind: 'Name', value: rootFieldName }, selectionSet: extractQuerySelectionSet(query, namedType.name, schema), }; return { fieldNodes: [fieldNode], fragments: {}, schema: schema, fieldName: rootFieldName, returnType: type, parentType: schema.getQueryType() || undefined, path: undefined, rootValue: undefined, operation: { kind: 'OperationDefinition', operation: operation, selectionSet: { kind: 'SelectionSet', selections: [] }, variableDefinitions: [], }, variableValues: {}, }; } exports.buildInfoFromFragment = buildInfoFromFragment; function extractQuerySelectionSet(query, typeName, schema) { if (!query.startsWith('fragment')) { query = "fragment tmp on " + typeName + " " + query; } var document = graphql_1.parse(query); var errors = graphql_1.validate(schema, document).filter(function (e) { return e.message.match(/Fragment ".*" is never used./) === null; }); if (errors.length > 0) { throw errors; } var queryNode = document.definitions[0]; if (!queryNode || queryNode.kind !== 'FragmentDefinition') { throw new Error("Invalid query: " + query); } return queryNode.selectionSet; } /** * Generates a sub info based on the provided path. If provided path is not included in the selection set, the function returns null. * @param info GraphQLResolveInfo * @param path string * @param fragment string | undefined */ function makeSubInfo(info, path, fragment) { var returnType = getDeepType(info.returnType); if (graphql_1.isScalarType(returnType)) { throw new Error("Can't make subInfo for type " + info.returnType.toString()); } var splittedPath = path.split('.'); var fieldsToTraverse = splittedPath.slice(); var currentType = info.returnType; var currentSelectionSet = info.fieldNodes[0].selectionSet; var currentFieldName; var parentType; var currentPath = info.path || { prev: undefined, key: info.fieldNodes[0].name.value, }; while (fieldsToTraverse.length > 0) { currentFieldName = fieldsToTraverse.shift(); if (!graphql_1.isObjectType(currentType)) { throw new Error("Can't get subInfo for type " + currentType.toString() + " as needs to be a GraphQLObjectType"); } var fields = currentType.getFields(); if (!fields[currentFieldName]) { throw new Error("Type " + currentType.toString() + " has no field called " + currentFieldName); } var currentFieldType = fields[currentFieldName].type; if (!graphql_1.isObjectType(currentFieldType)) { throw new Error("Can't get subInfo for type " + currentFieldType + " of field " + currentFieldName + " on type " + currentType.toString()); } parentType = currentType; currentType = currentFieldType; var suitableSelection = currentSelectionSet.selections.find(function (selection) { return selection.kind === 'Field' && selection.name.value === currentFieldName; }); if (!suitableSelection) { // if there is no field selection, there still could be fragments currentSelectionSet = currentSelectionSet.selections.reduce(function (acc, curr) { if (acc) { return acc; } if (curr.kind === 'InlineFragment') { return curr.selectionSet; } }, null); } else if (suitableSelection.kind === 'Field') { currentSelectionSet = suitableSelection.selectionSet; } if (!currentSelectionSet) { return null; } currentPath = addPath(currentPath, currentFieldName); } var fieldNode = { kind: 'Field', name: { kind: 'Name', value: currentFieldName }, selectionSet: currentSelectionSet, }; var newInfo = { fieldNodes: [fieldNode], fragments: {}, schema: info.schema, fieldName: currentFieldName, returnType: currentType, parentType: parentType, path: currentPath, rootValue: undefined, operation: { kind: graphql_1.Kind.OPERATION_DEFINITION, operation: currentFieldName, selectionSet: { kind: graphql_1.Kind.SELECTION_SET, selections: [] }, variableDefinitions: [], }, variableValues: {}, }; if (fragment) { return addFragmentToInfo_1.addFragmentToInfo(newInfo, fragment); } return newInfo; } exports.makeSubInfo = makeSubInfo; function getDeepType(type) { if (type.ofType) { return getDeepType(type.ofType); } return type; } exports.getDeepType = getDeepType; function addPath(prev, key) { return { prev: prev, key: key }; } exports.addPath = addPath; //# sourceMappingURL=info.js.map