@cran/gql.core
Version:
Cran/GraphQL Core Utilities
61 lines (60 loc) • 2.28 kB
JavaScript
import { PluginPhase } from "./Plugin";
import { MapperKind } from "@graphql-tools/utils";
import { createDirective } from "../utilities/createDirective";
import { isOutputType } from "graphql/type/definition";
import { patchField } from "../utilities/patchField";
import { __EnumValue, __Field, __InputValue, __Schema, __Type } from "graphql";
import { getExtension, setExtension } from "../utilities/extensions";
export const IntrospectionType = {
[MapperKind.ROOT_OBJECT]: __Schema,
[MapperKind.TYPE]: __Type,
[MapperKind.OBJECT_FIELD]: __Field,
[MapperKind.INPUT_OBJECT_FIELD]: __InputValue,
[MapperKind.ENUM_VALUE]: __EnumValue,
};
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: {
[PluginPhase.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 !== undefined ? value : fallback(source, key);
},
});
}
function alwaysNull() { return null; }