UNPKG

@cran/lib.gql.core

Version:

GQL Core Functionality

50 lines (49 loc) 1.79 kB
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; }