UNPKG

@graphql-mesh/fusion-composition

Version:

Basic composition utility for Fusion spec

257 lines (256 loc) • 11.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ignoreList = void 0; exports.createRenameTransform = createRenameTransform; exports.createRenameTypeTransform = createRenameTypeTransform; exports.createRenameFieldTransform = createRenameFieldTransform; const graphql_1 = require("graphql"); const graphql_scalars_1 = require("graphql-scalars"); const utils_1 = require("@graphql-tools/utils"); exports.ignoreList = [ 'Int', 'Float', 'String', 'Boolean', 'ID', 'date', 'hostname', 'regex', 'json-pointer', 'relative-json-pointer', 'uri-reference', 'uri-template', 'ObjMap', 'HttpMethod', ...Object.keys(graphql_scalars_1.resolvers), ]; // TODO: For backwards compatibility, remove in the next major function createRenameTransform(opts) { const typeRenamers = opts.typeRenamer ? [opts.typeRenamer] : []; const fieldRenamers = opts.fieldRenamer ? [opts.fieldRenamer] : []; const argRenamers = opts.argRenamer ? [opts.argRenamer] : []; if (opts.renames?.length) { for (const change of opts.renames) { const { from: { type: fromTypeName, field: fromFieldName, argument: fromArgumentName }, to: { type: toTypeName, field: toFieldName, argument: toArgumentName }, useRegExpForTypes, useRegExpForFields, useRegExpForArguments, } = change; const includeDefaults = change.includeDefaults === true; const regExpFlags = change.regExpFlags || undefined; if (fromTypeName !== toTypeName) { let replaceTypeNameFn; if (useRegExpForTypes) { const typeNameRegExp = new RegExp(fromTypeName, regExpFlags); replaceTypeNameFn = ({ typeName }) => typeName.replace(typeNameRegExp, toTypeName); } else { replaceTypeNameFn = ({ typeName }) => (typeName === fromTypeName ? toTypeName : typeName); } typeRenamers.push(({ typeName, type, subgraphConfig }) => { if (!includeDefaults && exports.ignoreList.includes(typeName)) { return typeName; } return replaceTypeNameFn({ typeName, type, subgraphConfig }); }); } if (fromFieldName && toFieldName && fromFieldName !== toFieldName) { let replaceFieldNameFn; if (useRegExpForFields) { const fieldNameRegExp = new RegExp(fromFieldName, regExpFlags); replaceFieldNameFn = ({ typeName, fieldName }) => typeName === toTypeName ? fieldName.replace(fieldNameRegExp, toFieldName) : fieldName; } else { replaceFieldNameFn = ({ typeName, fieldName }) => typeName === toTypeName && fieldName === fromFieldName ? toFieldName : fieldName; } fieldRenamers.push(replaceFieldNameFn); } if (fromTypeName && (fromTypeName === toTypeName || useRegExpForTypes) && toFieldName && (fromFieldName === toFieldName || useRegExpForFields) && fromArgumentName && fromArgumentName !== toArgumentName) { let replaceArgNameFn; const fieldNameMatch = (fieldName) => fieldName === (useRegExpForFields ? fieldName.replace(new RegExp(fromFieldName, regExpFlags), toFieldName) : toFieldName); const typeNameMatch = (typeName) => typeName === (useRegExpForTypes ? typeName.replace(new RegExp(fromTypeName, regExpFlags), toTypeName) : toTypeName); if (useRegExpForArguments) { const argNameRegExp = new RegExp(fromArgumentName, regExpFlags); replaceArgNameFn = ({ typeName, fieldName, argName }) => typeNameMatch(typeName) && fieldNameMatch(fieldName) ? argName.replace(argNameRegExp, toArgumentName) : argName; } else { replaceArgNameFn = ({ typeName, fieldName, argName }) => typeNameMatch(typeName) && fieldNameMatch(fieldName) && argName === fromArgumentName ? toArgumentName : argName; } argRenamers.push(replaceArgNameFn); } } } return function renameTransform(schema, subgraphConfig) { const schemaMapper = {}; const typeRenameMap = new Map(); if (typeRenamers.length) { schemaMapper[utils_1.MapperKind.TYPE] = type => { let newTypeName = type.name; for (const renamer of typeRenamers) { newTypeName = renamer({ typeName: newTypeName, type, subgraphConfig, }) || newTypeName; } if (newTypeName !== type.name) { typeRenameMap.set(type.name, newTypeName); return new (Object.getPrototypeOf(type).constructor)({ ...type.toConfig(), name: newTypeName, }); } return type; }; } const fieldRenameMap = new Map(); schemaMapper[utils_1.MapperKind.FIELD] = (field, fieldName, typeName, schema) => { let newFieldName = fieldName; if (fieldRenamers.length) { const type = schema.getType(typeName); for (const renamer of fieldRenamers) { newFieldName = renamer({ typeName, fieldName: newFieldName, type, field, subgraphConfig, }) || newFieldName; } let typeFieldRenameMap = fieldRenameMap.get(typeName); if (!typeFieldRenameMap) { typeFieldRenameMap = new Map(); fieldRenameMap.set(typeName, typeFieldRenameMap); } typeFieldRenameMap.set(fieldName, newFieldName); } const fieldDirectives = (0, utils_1.getDirectiveExtensions)(field, schema); if (fieldDirectives.resolveTo) { fieldDirectives.resolveTo = fieldDirectives.resolveTo.map(resolveTo => ({ ...resolveTo, sourceTypeName: (resolveTo.sourceTypeName && typeRenameMap.get(resolveTo.sourceTypeName)) || resolveTo.sourceTypeName, sourceFieldName: (resolveTo.sourceFieldName && fieldRenameMap.get(resolveTo.sourceTypeName)?.get(resolveTo.sourceFieldName)) || resolveTo.sourceFieldName, })); const fieldExtensions = (field.extensions ||= {}); fieldExtensions.directives = fieldDirectives; } if (argRenamers.length && 'args' in field && field.args) { const newArgs = {}; for (const argName in field.args) { let newArgName = argName; for (const renamer of argRenamers) { newArgName = renamer({ typeName, fieldName, argName: newArgName, subgraphConfig, }) || newArgName; } newArgs[newArgName] = field.args[argName]; } return [ newFieldName, { ...field, args: newArgs, }, ]; } return [newFieldName, field]; }; return (0, utils_1.mapSchema)(schema, schemaMapper); }; } function createRenameTypeTransform(renameFn, kind = utils_1.MapperKind.TYPE) { return function renameTypeTransform(schema, subgraphConfig) { const rootTypes = (0, utils_1.getRootTypes)(schema); const renamedTypeMap = new Map(); return (0, utils_1.mapSchema)(schema, { [kind]: type => { if ((0, graphql_1.isSpecifiedScalarType)(type) || rootTypes.has(type)) { return type; } const newName = renameFn({ typeName: type.name, type, subgraphConfig, }) || type.name; if (type.name === newName) { return type; } renamedTypeMap.set(type.name, newName); return new (Object.getPrototypeOf(type).constructor)({ ...type.toConfig(), name: newName, }); }, [utils_1.MapperKind.FIELD](field) { const fieldDirectives = (0, utils_1.getDirectiveExtensions)(field, schema); if (fieldDirectives?.resolveTo) { fieldDirectives.resolveTo = fieldDirectives.resolveTo.map(resolveTo => ({ ...resolveTo, sourceTypeName: renamedTypeMap.get(resolveTo.sourceTypeName) || resolveTo.sourceTypeName, })); } const fieldExtensions = (field.extensions ||= {}); fieldExtensions.directives = fieldDirectives; return field; }, }); }; } function createRenameFieldTransform(renameFn, kind = utils_1.MapperKind.FIELD) { return function renameFieldTransform(schema, subgraphConfig) { const fieldRenameMap = new Map(); const mapper = { [kind]: (field, fieldName, typeName) => { const type = schema.getType(typeName); const newFieldName = renameFn({ typeName, fieldName, type, field, subgraphConfig, }) || fieldName; let typeFieldRenameMap = fieldRenameMap.get(typeName); if (!typeFieldRenameMap) { typeFieldRenameMap = new Map(); fieldRenameMap.set(typeName, typeFieldRenameMap); } typeFieldRenameMap.set(fieldName, newFieldName); return [newFieldName, resolveToUpdater(field, schema)]; }, }; function resolveToUpdater(field, schema) { const fieldDirectives = (0, utils_1.getDirectiveExtensions)(field, schema); if (fieldDirectives?.resolveTo) { fieldDirectives.resolveTo = fieldDirectives.resolveTo.map(resolveTo => ({ ...resolveTo, sourceFieldName: fieldRenameMap.get(resolveTo.sourceTypeName)?.get(resolveTo.sourceFieldName) || resolveTo.sourceFieldName, })); } const fieldExtensions = (field.extensions ||= {}); fieldExtensions.directives = fieldDirectives; return field; } return (0, utils_1.mapSchema)(schema, mapper); }; }