@graphql-mesh/transform-rename
Version:
125 lines (124 loc) • 6.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const graphql_1 = require("graphql");
const utils_1 = require("@graphql-tools/utils");
const shared_js_1 = require("./shared.js");
// Resolver composer mapping renamed field and arguments
const defaultResolverComposer = (resolveFn = graphql_1.defaultFieldResolver, originalFieldName, argsMap) => (root, args, context, info) => resolveFn(root,
// map renamed arguments to their original value
argsMap
? Object.keys(args).reduce((acc, key) => ({ ...acc, [argsMap[key] || key]: args[key] }), {})
: args, context,
// map renamed field name to its original value
originalFieldName ? { ...info, fieldName: originalFieldName } : info);
class BareRename {
constructor({ config }) {
this.noWrap = true;
this.typesMap = new Map();
this.fieldsMap = new Map();
this.argsMap = new Map();
for (const rename of config.renames) {
const { from: { type: fromTypeName, field: fromFieldName, argument: fromArgName }, to: { type: toTypeName, field: toFieldName, argument: toArgName }, useRegExpForTypes, useRegExpForFields, } = rename;
const regExpFlags = rename.regExpFlags || undefined;
if (fromTypeName &&
!fromFieldName &&
toTypeName &&
!toFieldName &&
fromTypeName !== toTypeName) {
this.typesMap.set(useRegExpForTypes ? new RegExp(fromTypeName, regExpFlags) : fromTypeName, toTypeName);
}
if (fromTypeName &&
fromFieldName &&
toTypeName &&
toFieldName &&
fromFieldName !== toFieldName) {
const fromName = useRegExpForFields
? new RegExp(fromFieldName, regExpFlags)
: fromFieldName;
const typeMap = this.fieldsMap.get(fromTypeName) || new Map();
this.fieldsMap.set(fromTypeName, typeMap.set(fromName, toFieldName));
}
if (fromTypeName &&
fromFieldName &&
fromArgName &&
toTypeName &&
toFieldName &&
toArgName &&
fromArgName !== toArgName) {
const fromName = useRegExpForFields ? new RegExp(fromArgName, regExpFlags) : fromArgName;
const key = `${fromTypeName}.${fromFieldName}`;
const typeMap = this.argsMap.get(key) || new Map();
this.argsMap.set(key, typeMap.set(fromName, toArgName));
}
}
}
matchInMap(map, toMatch) {
const mapKeyIsString = map.has(toMatch);
const mapKey = mapKeyIsString
? toMatch
: [...map.keys()].find(key => typeof key !== 'string' && key.test(toMatch));
if (!mapKey)
return null;
const newName = mapKeyIsString ? map.get(mapKey) : toMatch.replace(mapKey, map.get(mapKey));
// avoid re-iterating over strings that have already been renamed
if (mapKeyIsString)
map.delete(mapKey);
return newName;
}
renameType(type) {
const newTypeName = shared_js_1.ignoreList.includes(type.toString())
? null
: this.matchInMap(this.typesMap, type.toString());
return newTypeName ? (0, utils_1.renameType)(type, newTypeName) : undefined;
}
transformSchema(schema) {
return (0, utils_1.mapSchema)(schema, {
...(this.typesMap.size && {
[utils_1.MapperKind.TYPE]: type => this.renameType(type),
[utils_1.MapperKind.ABSTRACT_TYPE]: type => {
const currentName = type.toString();
const newName = shared_js_1.ignoreList.includes(currentName)
? null
: this.matchInMap(this.typesMap, currentName);
const existingResolver = type.resolveType;
type.resolveType = async (data, context, info, abstractType) => {
const originalResolvedTypename = await existingResolver(data, context, info, abstractType);
const newTypename = shared_js_1.ignoreList.includes(originalResolvedTypename)
? null
: this.matchInMap(this.typesMap, originalResolvedTypename);
return newTypename || originalResolvedTypename;
};
if (newName && newName !== currentName) {
return (0, utils_1.renameType)(type, newName);
}
return undefined;
},
[utils_1.MapperKind.ROOT_OBJECT]: type => this.renameType(type),
}),
...((this.fieldsMap.size || this.argsMap.size) && {
[utils_1.MapperKind.COMPOSITE_FIELD]: (fieldConfig, fieldName, typeName) => {
const typeRules = this.fieldsMap.get(typeName);
const fieldRules = this.argsMap.get(`${typeName}.${fieldName}`);
const newFieldName = typeRules && this.matchInMap(typeRules, fieldName);
const argsMap = fieldRules &&
Array.from(fieldRules.entries()).reduce((acc, [orName, newName]) => ({ ...acc, [newName]: orName }), {});
if (!newFieldName && !fieldRules)
return undefined;
// Rename rules for type might have been emptied by matchInMap, in which case we can cleanup
if (!(typeRules === null || typeRules === void 0 ? void 0 : typeRules.size))
this.fieldsMap.delete(typeName);
if (fieldRules && fieldConfig.args) {
fieldConfig.args = Object.entries(fieldConfig.args).reduce((args, [argName, argConfig]) => ({
...args,
[this.matchInMap(fieldRules, argName) || argName]: argConfig,
}), {});
}
// Wrap resolve fn to handle mapping renamed field name and/or renamed arguments
fieldConfig.resolve = defaultResolverComposer(fieldConfig.resolve, fieldName, argsMap);
return [newFieldName || fieldName, fieldConfig];
},
}),
});
}
}
exports.default = BareRename;