UNPKG

apollo-language-server

Version:

A language server for Apollo GraphQL projects

195 lines 7.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hasClientDirective = exports.simpleCollectFields = exports.withTypenameFieldAddedWhereNeeded = exports.removeDirectiveAnnotatedFields = exports.removeDirectives = exports.getFieldDef = exports.highlightNodeForNode = exports.isDirectiveDefinitionNode = exports.isNamedNode = exports.isNode = void 0; const graphql_1 = require("graphql"); function isNode(maybeNode) { return maybeNode && typeof maybeNode.kind === "string"; } exports.isNode = isNode; function isNamedNode(node) { return "name" in node; } exports.isNamedNode = isNamedNode; function isDirectiveDefinitionNode(node) { return node.kind === graphql_1.Kind.DIRECTIVE_DEFINITION; } exports.isDirectiveDefinitionNode = isDirectiveDefinitionNode; function highlightNodeForNode(node) { switch (node.kind) { case graphql_1.Kind.VARIABLE_DEFINITION: return node.variable; default: return isNamedNode(node) ? node.name : node; } } exports.highlightNodeForNode = highlightNodeForNode; function getFieldDef(schema, parentType, fieldAST) { const name = fieldAST.name.value; if (name === graphql_1.SchemaMetaFieldDef.name && schema.getQueryType() === parentType) { return graphql_1.SchemaMetaFieldDef; } if (name === graphql_1.TypeMetaFieldDef.name && schema.getQueryType() === parentType) { return graphql_1.TypeMetaFieldDef; } if (name === graphql_1.TypeNameMetaFieldDef.name && ((0, graphql_1.isObjectType)(parentType) || (0, graphql_1.isInterfaceType)(parentType) || (0, graphql_1.isUnionType)(parentType))) { return graphql_1.TypeNameMetaFieldDef; } if ((0, graphql_1.isObjectType)(parentType) || (0, graphql_1.isInterfaceType)(parentType)) { return parentType.getFields()[name]; } return undefined; } exports.getFieldDef = getFieldDef; function removeDirectives(ast, directiveNames) { if (!directiveNames.length) return ast; return (0, graphql_1.visit)(ast, { Directive(node) { if (!!directiveNames.find((name) => name === node.name.value)) return null; return node; }, }); } exports.removeDirectives = removeDirectives; function removeOrphanedFragmentDefinitions(ast, fragmentNamesEligibleForRemoval) { let anyFragmentsRemoved = false; const fragmentSpreadNodeNames = new Set(); (0, graphql_1.visit)(ast, { FragmentSpread(node) { fragmentSpreadNodeNames.add(node.name.value); }, }); ast = (0, graphql_1.visit)(ast, { FragmentDefinition(node) { if (fragmentNamesEligibleForRemoval.has(node.name.value) && !fragmentSpreadNodeNames.has(node.name.value)) { anyFragmentsRemoved = true; return null; } return undefined; }, }); if (anyFragmentsRemoved) { return removeOrphanedFragmentDefinitions(ast, fragmentNamesEligibleForRemoval); } return ast; } function removeNodesWithEmptySelectionSets(ast) { ast = (0, graphql_1.visit)(ast, { enter(node) { return "selectionSet" in node && node.selectionSet != null && node.selectionSet.selections.length === 0 ? null : undefined; }, }); return ast; } function removeDirectiveAnnotatedFields(ast, directiveNames) { graphql_1.print; if (!directiveNames.length) return ast; const removedFragmentDefinitionNames = new Set(); const removedFragmentSpreadNames = new Set(); ast = (0, graphql_1.visit)(ast, { enter(node) { if ("directives" in node && node.directives && node.directives.find((directive) => directiveNames.includes(directive.name.value))) { if (node.kind === graphql_1.Kind.FRAGMENT_DEFINITION) { removedFragmentDefinitionNames.add(node.name.value); } (0, graphql_1.visit)(node, { FragmentSpread(node) { removedFragmentSpreadNames.add(node.name.value); }, }); return null; } return undefined; }, }); ast = (0, graphql_1.visit)(ast, { FragmentSpread(node) { if (removedFragmentDefinitionNames.has(node.name.value)) { removedFragmentSpreadNames.add(node.name.value); return null; } return undefined; }, }); ast = removeOrphanedFragmentDefinitions(ast, removedFragmentSpreadNames); return removeNodesWithEmptySelectionSets(ast); } exports.removeDirectiveAnnotatedFields = removeDirectiveAnnotatedFields; const typenameField = { kind: graphql_1.Kind.FIELD, name: { kind: graphql_1.Kind.NAME, value: "__typename" }, }; function withTypenameFieldAddedWhereNeeded(ast) { return (0, graphql_1.visit)(ast, { enter: { SelectionSet(node) { return Object.assign(Object.assign({}, node), { selections: node.selections.filter((selection) => !(selection.kind === "Field" && selection.name.value === "__typename")) }); }, }, leave(node) { if (!(node.kind === graphql_1.Kind.FIELD || node.kind === graphql_1.Kind.FRAGMENT_DEFINITION || node.kind === graphql_1.Kind.INLINE_FRAGMENT)) { return undefined; } if (!node.selectionSet) return undefined; return Object.assign(Object.assign({}, node), { selectionSet: Object.assign(Object.assign({}, node.selectionSet), { selections: [typenameField, ...node.selectionSet.selections] }) }); }, }); } exports.withTypenameFieldAddedWhereNeeded = withTypenameFieldAddedWhereNeeded; function getFieldEntryKey(node) { return node.alias ? node.alias.value : node.name.value; } function simpleCollectFields(context, selectionSet, fields, visitedFragmentNames) { for (const selection of selectionSet.selections) { switch (selection.kind) { case graphql_1.Kind.FIELD: { const name = getFieldEntryKey(selection); if (!fields[name]) { fields[name] = []; } fields[name].push(selection); break; } case graphql_1.Kind.INLINE_FRAGMENT: { simpleCollectFields(context, selection.selectionSet, fields, visitedFragmentNames); break; } case graphql_1.Kind.FRAGMENT_SPREAD: { const fragName = selection.name.value; if (visitedFragmentNames[fragName]) continue; visitedFragmentNames[fragName] = true; const fragment = context.fragments[fragName]; if (!fragment) continue; simpleCollectFields(context, fragment.selectionSet, fields, visitedFragmentNames); break; } } } return fields; } exports.simpleCollectFields = simpleCollectFields; function hasClientDirective(node) { return (node.directives && node.directives.some((directive) => directive.name.value === "client")); } exports.hasClientDirective = hasClientDirective; //# sourceMappingURL=graphql.js.map