UNPKG

@graphql-mesh/fusion-composition

Version:

Basic composition utility for Fusion spec

183 lines (182 loc) • 6.91 kB
import { extendSchema, isSpecifiedScalarType, parse, parseType, typeFromAST, } from 'graphql'; import { getRootTypes, MapperKind, mapSchema } from '@graphql-tools/utils'; import { getDirectiveExtensions } from './getDirectiveExtensions.js'; export function createRenameTypeTransform(renameFn, kind = MapperKind.TYPE) { return function renameTypeTransform(schema, subgraphConfig) { return mapSchema(schema, { [kind]: (type) => isSpecifiedScalarType(type) ? type : new (Object.getPrototypeOf(type).constructor)({ ...type.toConfig(), name: renameFn(type, subgraphConfig) || type.name, }), }); }; } export function createRenameFieldTransform(renameFn, kind = MapperKind.FIELD) { return function renameFieldTransform(schema, subgraphConfig) { return mapSchema(schema, { [kind]: (field, fieldName, typeName) => [renameFn(field, fieldName, typeName, subgraphConfig) || fieldName, field], }); }; } export function createPrefixTransform({ value, ignore = [], includeRootOperations = false, includeTypes = true, } = {}) { return function prefixTransform(schema, subgraphConfig) { value = value || subgraphConfig.name; const transforms = []; const rootTypeNames = [...getRootTypes(schema)].map(type => type.name); if (includeTypes) { transforms.push(createRenameTypeTransform(type => { if (ignore.includes(type.name)) { return type.name; } return `${value}${type.name}`; })); } if (includeRootOperations) { transforms.push(createRenameFieldTransform((_field, fieldName, typeName) => { if (rootTypeNames.includes(typeName) && !ignore.includes(typeName)) { return `${value}${fieldName}`; } return fieldName; }, MapperKind.ROOT_FIELD)); } for (const transform of transforms) { schema = transform(schema, subgraphConfig); } return schema; }; } function addHiddenDirective(directableObj) { const directives = getDirectiveExtensions(directableObj); directives.hidden = [{}]; const extensions = (directableObj.extensions ||= {}); extensions.directives = directives; } export function createFilterTransform(config) { const schemaMapper = {}; if (config.rootFieldFilter) { schemaMapper[MapperKind.ROOT_FIELD] = (fieldConfig, fieldName, typeName) => { if (!config.rootFieldFilter(typeName, fieldName)) { addHiddenDirective(fieldConfig); } return [fieldName, fieldConfig]; }; } if (config.typeFilter) { schemaMapper[MapperKind.TYPE] = type => { if (!config.typeFilter(type)) { addHiddenDirective(type); } return type; }; } if (config.fieldFilter) { schemaMapper[MapperKind.FIELD] = (fieldConfig, fieldName, typeName) => { if (!config.fieldFilter(typeName, fieldName)) { addHiddenDirective(fieldConfig); } return fieldConfig; }; } if (config.objectFieldFilter) { schemaMapper[MapperKind.OBJECT_FIELD] = (fieldConfig, fieldName, typeName) => { if (!config.objectFieldFilter(typeName, fieldName)) { addHiddenDirective(fieldConfig); } return [fieldName, fieldConfig]; }; } if (config.interfaceFieldFilter) { schemaMapper[MapperKind.INTERFACE_FIELD] = (fieldConfig, fieldName, typeName) => { if (!config.interfaceFieldFilter(typeName, fieldName)) { addHiddenDirective(fieldConfig); } return [fieldName, fieldConfig]; }; } if (config.inputObjectFieldFilter) { schemaMapper[MapperKind.INPUT_OBJECT_FIELD] = (fieldConfig, fieldName, typeName) => { if (!config.inputObjectFieldFilter(typeName, fieldName)) { addHiddenDirective(fieldConfig); } return fieldConfig; }; } // TODO /* if (config.argumentFilter) { schemaMapper[MapperKind.ARGUMENT] = (argConfig, fieldName, typeName) => { if (config.argumentFilter(typeName, fieldName, argConfig)) { return argConfig; } return null; }; } */ return function filterTransform(schema) { return mapSchema(schema, schemaMapper); }; } export * from 'change-case'; export function createNamingConventionTransform(config) { const schemaMapper = {}; if (config.typeNames) { schemaMapper[MapperKind.TYPE] = type => { if (isSpecifiedScalarType(type)) { return type; } return new (Object.getPrototypeOf(type).constructor)({ ...type.toConfig(), name: config.typeNames(type.name), }); }; } if (config.fieldNames) { schemaMapper[MapperKind.FIELD] = (fieldConfig, fieldName) => [ config.fieldNames(fieldName), fieldConfig, ]; } if (config.enumValues) { schemaMapper[MapperKind.ENUM_VALUE] = (valueConfig, _typeName, _schema, externalValue) => [ config.enumValues(externalValue), valueConfig, ]; } if (config.fieldArgumentNames) { schemaMapper[MapperKind.ARGUMENT] = (argumentConfig, argumentName) => ({ ...argumentConfig, name: config.fieldArgumentNames(argumentName), }); } return function namingConventionTransform(schema) { return mapSchema(schema, schemaMapper); }; } export function createTypeReplaceTransform(replacerFn) { return function typeReplaceTransform(schema) { return mapSchema(schema, { [MapperKind.FIELD]: (fieldConfig, fieldName, typeName) => { const newTypeName = replacerFn(typeName, fieldName, fieldConfig.type); if (newTypeName) { const newType = typeFromAST(schema, parseType(newTypeName)); if (!newType) { throw new Error(`No type found for ${newTypeName}`); } return [fieldName, { ...fieldConfig, type: newType }]; } return undefined; }, }); }; } export function createExtendTransform(typeDefs) { const typeDefsDoc = typeof typeDefs === 'string' ? parse(typeDefs, { noLocation: true }) : typeDefs; return function extendTransform(schema) { return extendSchema(schema, typeDefsDoc, { assumeValid: true, assumeValidSDL: true, }); }; }