"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getProjectionFromAST = getProjectionFromAST; exports.getProjectionFromASTquery = getProjectionFromASTquery; exports.getFlatProjectionFromAST = getFlatProjectionFromAST; exports.extendByFieldProjection = extendByFieldProjection; var _graphql = require("../graphql"); var _deepmerge = _interopRequireDefault(require("./deepmerge")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* eslint-disable no-param-reassign, no-lonely-if */ const FIELD = _graphql.Kind.FIELD, FRAGMENT_SPREAD = _graphql.Kind.FRAGMENT_SPREAD, INLINE_FRAGMENT = _graphql.Kind.INLINE_FRAGMENT; // export type ProjectionType = { [fieldName: string]: $Shape | true }; // export type ProjectionNode = { [fieldName: string]: $Shape } | true; function getProjectionFromAST(info, fieldNode) { if (!info) { return {}; } const queryProjection = getProjectionFromASTquery(info, fieldNode); const queryExtProjection = extendByFieldProjection(info.returnType, queryProjection); return queryExtProjection; } function getProjectionFromASTquery(info, fieldNode) { if (!info) { return {}; } let selections; // Array; if (fieldNode) { if (fieldNode.selectionSet) { selections = fieldNode.selectionSet.selections; } } else if (Array.isArray(info.fieldNodes)) { // get all selectionSets selections = info.fieldNodes.reduce((result, source) => { if (source.selectionSet) { result.push(...source.selectionSet.selections); } return result; }, []); } const projection = (selections || []).reduce((res, ast) => { switch (ast.kind) { case FIELD: { const value = ast.name.value; if (res[value]) { res[value] = (0, _deepmerge.default)(res[value], getProjectionFromASTquery(info, ast) || true); } else { res[value] = getProjectionFromASTquery(info, ast) || true; } return res; } case INLINE_FRAGMENT: return (0, _deepmerge.default)(res, getProjectionFromASTquery(info, ast)); case FRAGMENT_SPREAD: return (0, _deepmerge.default)(res, getProjectionFromASTquery(info, info.fragments[ast.name.value])); default: throw new Error('Unsuported query selection'); } }, {}); return projection; } function getFlatProjectionFromAST(info, fieldNodes) { const projection = getProjectionFromAST(info, fieldNodes) || {}; const flatProjection = {}; Object.keys(projection).forEach(key => { flatProjection[key] = !!projection[key]; }); return flatProjection; } // This method traverse fields and extends current projection // by projection from fields function extendByFieldProjection(returnType, projection) { let type = returnType; while (type instanceof _graphql.GraphQLList || type instanceof _graphql.GraphQLNonNull) { type = type.ofType; } if (!(type instanceof _graphql.GraphQLObjectType || type instanceof _graphql.GraphQLInterfaceType)) { return projection; } let proj = projection; Object.keys(proj).forEach(key => { const field = type._fields[key]; if (!field) return; if (field.projection) proj = (0, _deepmerge.default)(proj, field.projection); if (field.extensions && field.extensions.projection) { proj = (0, _deepmerge.default)(proj, field.extensions.projection); } proj[key] = extendByFieldProjection(field.type, proj[key]); }); return proj; }