@cran/lib.gql.core
Version:
GQL Core Functionality
50 lines (49 loc) • 1.79 kB
JavaScript
import { isOutputType, } from "graphql";
import { Plugin } from "./Plugin";
import { IntrospectionType, createDirective, getExtension, patchField, setExtension, } from "../utilities";
export function withMetadata(options) {
const plugins = [];
for (const key in options.fields) {
if ("default" !== key) {
const kind = key;
plugins.push(createDirective(options.names?.[kind] ?? `${IntrospectionType[kind].name.slice(2)}Metadata`, { ...options.fields.default, ...options.fields[kind], }, { [kind]: directiveMapper, }));
}
}
plugins.push({
transformer: {
[Plugin.Phase.FINALIZE](schema) {
for (const name in options.fields) {
if ("default" !== name) {
addFields(schema, name, options);
}
}
return schema;
},
},
});
return plugins;
}
function directiveMapper([directive,], type) {
setExtension(type, "metadata", directive);
}
function addFields(schema, kind, options) {
const field = options.fields[kind];
for (const key in field) {
const type = schema.getType(field[key]);
if (!type || !isOutputType(type)) {
throw new TypeError(`MetadataPlugin expects "GraphQLOutputType" received "${type?.name}"`);
}
addField(kind, key, type, options);
}
}
function addField(kind, key, type, options) {
const fallback = options.fallbacks?.[kind] || alwaysNull;
patchField(IntrospectionType[kind], key, {
type,
resolve(source) {
const value = getExtension(source, "metadata")?.[key];
return value ?? fallback(source, key);
},
});
}
function alwaysNull() { return null; }