@cran/gql.core
Version:
Cran/GraphQL Core Utilities
83 lines (82 loc) • 3.41 kB
JavaScript
import { parseLiteral } from "./parse";
import { MapperKind, getDirective, mapSchema } from "@graphql-tools/utils";
import { isDirective, isSchema } from "graphql";
const Location = {
[]: ["SCALAR", "OBJECT", "INTERFACE", "UNION", "ENUM", "INPUT_OBJECT",],
[]: ["SCALAR",],
[]: ["ENUM",],
[]: ["OBJECT", "INTERFACE", "UNION",],
[]: ["OBJECT",],
[]: ["INPUT_OBJECT",],
[]: ["INTERFACE", "UNION",],
[]: ["UNION_TYPE",],
[]: ["INTERFACE",],
[]: ["SCHEMA",],
[]: ["OBJECT",],
[]: ["OBJECT",],
[]: ["OBJECT",],
[]: ["ENUM_VALUE",],
[]: ["FIELD_DEFINITION", "INPUT_FIELD_DEFINITION",],
[]: ["FIELD_DEFINITION",],
[]: ["FIELD_DEFINITION",],
[]: ["FIELD_DEFINITION",],
[]: ["FIELD_DEFINITION",],
[]: ["FIELD_DEFINITION",],
[]: ["FIELD_DEFINITION",],
[]: ["FIELD_DEFINITION",],
[]: ["ARUGMENT_DEFINITION",],
[]: ["INPUT_FIELD_DEFINITION",],
[]: ["DIRECTIVE",],
};
function location(keys) {
const locations = [];
for (const key of keys) {
locations.push(...Location[key]);
}
return ([...new Set(locations),]).join("|");
}
export function createDirective(name, args, mapper) {
const argList = Object.keys(args).length ? `(${Object.entries(args).map(function mapArg([key, value,]) {
return `${key}:${value}`;
}).join(",")})` : "";
return {
typeDefs: `directive @${name}${argList} on ${location(Object.keys(mapper))}`,
transformer(schema) {
return mapSchema(schema, wrapSchemaMapper(name, mapper));
},
};
}
function wrapSchemaMapper(name, mapper) {
const wrapped = {};
for (const key in mapper) {
wrapped[key] = wrapMapper(name, mapper[key]);
}
return wrapped;
}
function wrapMapper(name, mapperFunction) {
return function mapper(...args) {
const [type,] = args;
if (isDirective(type)) {
return mapperFunction([], ...args) || type;
}
const directives = getDirective(args.find(isSchema), type, name) || getAstDirective(type, name);
if (directives?.[0]) {
return mapperFunction(directives, ...args) || type;
}
return type;
};
}
function getAstDirective(type, name) {
if (type.astNode && "directives" in type.astNode && type.astNode.directives) {
return type.astNode.directives.filter(function filterDir(directive) {
return directive.name.value === name;
}).map(function mapDir(directive) {
return directive.arguments?.reduce(function reduceArg(acc, arg) {
const { name: { value: argName, }, value, } = arg;
acc[argName] = parseLiteral("value" in value ? String(value.value) : "null", value);
return acc;
}, {}) || {};
});
}
return [];
}