@graphql-tools/merge
Version:
A set of utils for faster development of GraphQL tools
57 lines (56 loc) • 2.39 kB
JavaScript
import { versionInfo } from 'graphql';
import { mergeDeep } from '@graphql-tools/utils';
export { extractExtensionsFromSchema } from '@graphql-tools/utils';
// versionInfo exists from graphql@14.4.0; older 14.0.x peers omit it (still in ^14.0.0 range).
const mergeExtensionsOptions = versionInfo?.major >= 17
? {
respectArrays: true,
respectSymbols: { enumerable: true, nonEnumerable: true },
}
: { respectArrays: true };
export function mergeExtensions(extensions) {
return mergeDeep(extensions, mergeExtensionsOptions);
}
function applyExtensionObject(obj, extensions) {
if (!obj || !extensions || extensions === obj.extensions) {
return;
}
if (!obj.extensions) {
obj.extensions = extensions;
return;
}
obj.extensions = mergeDeep([obj.extensions, extensions], mergeExtensionsOptions);
}
export function applyExtensions(schema, extensions) {
applyExtensionObject(schema, extensions.schemaExtensions);
for (const [typeName, data] of Object.entries(extensions.types || {})) {
const type = schema.getType(typeName);
if (type) {
applyExtensionObject(type, data.extensions);
if (data.type === 'object' || data.type === 'interface') {
for (const [fieldName, fieldData] of Object.entries(data.fields)) {
const field = type.getFields()[fieldName];
if (field) {
applyExtensionObject(field, fieldData.extensions);
for (const [arg, argData] of Object.entries(fieldData.arguments)) {
applyExtensionObject(field.args.find(a => a.name === arg), argData);
}
}
}
}
else if (data.type === 'input') {
for (const [fieldName, fieldData] of Object.entries(data.fields)) {
const field = type.getFields()[fieldName];
applyExtensionObject(field, fieldData.extensions);
}
}
else if (data.type === 'enum') {
for (const [valueName, valueData] of Object.entries(data.values)) {
const value = type.getValue(valueName);
applyExtensionObject(value, valueData);
}
}
}
}
return schema;
}