UNPKG

@graphql-tools/federation

Version:

Useful tools to create and manipulate GraphQL schemas.

153 lines (152 loc) • 6.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getNamedTypeNode = exports.filterInternalFieldsAndTypes = exports.getCacheKeyFnFromKey = exports.getKeyFnForFederation = exports.projectDataSelectionSet = exports.getKeyForFederation = exports.getArgsFromKeysForFederation = void 0; const graphql_1 = require("graphql"); const utils_1 = require("@graphql-tools/utils"); function getArgsFromKeysForFederation(representations) { return { representations }; } exports.getArgsFromKeysForFederation = getArgsFromKeysForFederation; function getKeyForFederation(root) { return root; } exports.getKeyForFederation = getKeyForFederation; function projectDataSelectionSet(data, selectionSet) { if (data == null || selectionSet == null) { return data; } if (Array.isArray(data)) { return data.map(entry => projectDataSelectionSet(entry, selectionSet)); } const projectedData = { __typename: data.__typename, }; for (const selection of selectionSet.selections) { if (selection.kind === graphql_1.Kind.FIELD) { const key = selection.name.value; if (data.hasOwnProperty(key)) { const projectedKeyData = projectDataSelectionSet(data[key], selection.selectionSet); if (projectedData[key]) { projectedData[key] = (0, utils_1.mergeDeep)([projectedData[key], projectedKeyData]); } else { projectedData[key] = projectDataSelectionSet(data[key], selection.selectionSet); } } } else if (selection.kind === graphql_1.Kind.INLINE_FRAGMENT) { if (selection.typeCondition && projectedData['__typename'] != null && projectedData['__typename'] !== selection.typeCondition.name.value) { continue; } Object.assign(projectedData, (0, utils_1.mergeDeep)([projectedData, projectDataSelectionSet(data, selection.selectionSet)])); } } return projectedData; } exports.projectDataSelectionSet = projectDataSelectionSet; function getKeyFnForFederation(typeName, keys) { if (keys.some(key => key.includes('{'))) { const parsedSelectionSet = (0, utils_1.parseSelectionSet)(`{${keys.join(' ')}}`, { noLocation: true }); return function keyFn(root) { return projectDataSelectionSet({ __typename: typeName, ...root, }, parsedSelectionSet); }; } const allKeyProps = keys.flatMap(key => key.split(' ')).map(key => key.trim()); if (allKeyProps.length > 1) { return function keyFn(root) { return allKeyProps.reduce((prev, key) => { if (key !== '__typename') { prev[key] = root[key]; } return prev; }, { __typename: typeName }); }; } const keyProp = allKeyProps[0]; return function keyFn(root) { return { __typename: typeName, [keyProp]: root[keyProp], }; }; } exports.getKeyFnForFederation = getKeyFnForFederation; function getCacheKeyFnFromKey(key) { if (key.includes('{')) { const parsedSelectionSet = (0, utils_1.parseSelectionSet)(`{${key}}`, { noLocation: true }); return function cacheKeyFn(root) { return JSON.stringify(projectDataSelectionSet(root, parsedSelectionSet)); }; } const keyTrimmed = key.trim(); const keys = keyTrimmed.split(' ').map(key => key.trim()); if (keys.length > 1) { return function cacheKeyFn(root) { return keys.map(key => root[key]).join(' '); }; } return function cacheKeyFn(root) { return root[keyTrimmed]; }; } exports.getCacheKeyFnFromKey = getCacheKeyFnFromKey; const internalTypeNames = ['_Entity', '_Any', '_FieldSet', '_Service', 'link', 'inaccessible']; function filterInternalFieldsAndTypes(finalSchema) { return (0, utils_1.mapSchema)(finalSchema, { [utils_1.MapperKind.DIRECTIVE]: directive => { if (internalTypeNames.includes(directive.name) || directive.name.startsWith('link__') || directive.name.startsWith('join__') || directive.name.startsWith('core__')) { return null; } return directive; }, [utils_1.MapperKind.TYPE]: type => { if (internalTypeNames.includes(type.name) || type.name.startsWith('link__') || type.name.startsWith('join__') || type.name.startsWith('core__') || type.astNode?.directives?.some(d => d.name.value === 'inaccessible')) { return null; } return type; }, [utils_1.MapperKind.COMPOSITE_FIELD]: fieldConfig => { if (fieldConfig.astNode?.directives?.some(d => d.name.value === 'inaccessible')) { return null; } return fieldConfig; }, [utils_1.MapperKind.QUERY_ROOT_FIELD]: (fieldConfig, fieldName) => { if (fieldName === '_entities') { return null; } return fieldConfig; }, [utils_1.MapperKind.ENUM_VALUE]: valueConfig => { if (valueConfig.astNode?.directives?.some(d => d.name.value === 'inaccessible')) { return null; } }, [utils_1.MapperKind.ARGUMENT]: argConfig => { if (argConfig.astNode?.directives?.some(d => d.name.value === 'inaccessible')) { return null; } return argConfig; }, }); } exports.filterInternalFieldsAndTypes = filterInternalFieldsAndTypes; function getNamedTypeNode(typeNode) { if (typeNode.kind !== graphql_1.Kind.NAMED_TYPE) { return getNamedTypeNode(typeNode.type); } return typeNode; } exports.getNamedTypeNode = getNamedTypeNode;