graphql-compose
Version:
GraphQL schema builder from different data sources with middleware extensions.
932 lines • 41.9 kB
JavaScript
;
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeMapper = void 0;
exports.getDescription = getDescription;
const parser_1 = require("graphql/language/parser");
const language_1 = require("graphql/language");
const misc_1 = require("./utils/misc");
const values_1 = require("graphql/execution/values");
const deprecate_1 = __importDefault(require("./utils/deprecate"));
const misc_2 = require("./utils/misc");
const graphql_1 = require("./graphql");
const type_1 = require("./type");
const ObjectTypeComposer_1 = require("./ObjectTypeComposer");
const InputTypeComposer_1 = require("./InputTypeComposer");
const ScalarTypeComposer_1 = require("./ScalarTypeComposer");
const EnumTypeComposer_1 = require("./EnumTypeComposer");
const InterfaceTypeComposer_1 = require("./InterfaceTypeComposer");
const UnionTypeComposer_1 = require("./UnionTypeComposer");
const ListComposer_1 = require("./ListComposer");
const NonNullComposer_1 = require("./NonNullComposer");
const ThunkComposer_1 = require("./ThunkComposer");
const Resolver_1 = require("./Resolver");
const TypeStorage_1 = require("./TypeStorage");
const is_1 = require("./utils/is");
const typeHelpers_1 = require("./utils/typeHelpers");
const definitionNode_1 = require("./utils/definitionNode");
const blockString_1 = require("graphql/language/blockString");
class TypeMapper {
constructor(schemaComposer) {
if (!schemaComposer) {
throw new Error('TypeMapper must have SchemaComposer instance.');
}
this.schemaComposer = schemaComposer;
}
static isOutputType(type) {
(0, deprecate_1.default)("Use `import { isSomeOutputTypeComposer } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isSomeOutputTypeComposer)(type);
}
static isInputType(type) {
(0, deprecate_1.default)("Use `import { isSomeInputTypeComposer } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isSomeInputTypeComposer)(type);
}
static isTypeNameString(str) {
(0, deprecate_1.default)("Use `import { isTypeNameString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isTypeNameString)(str);
}
static isTypeDefinitionString(str) {
(0, deprecate_1.default)("Use `import { isTypeDefinitionString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isTypeDefinitionString)(str);
}
static isOutputTypeDefinitionString(str) {
(0, deprecate_1.default)("Use `import { isOutputTypeDefinitionString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isOutputTypeDefinitionString)(str);
}
static isInputTypeDefinitionString(str) {
(0, deprecate_1.default)("Use `import { isInputTypeDefinitionString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isInputTypeDefinitionString)(str);
}
static isEnumTypeDefinitionString(str) {
(0, deprecate_1.default)("Use `import { isEnumTypeDefinitionString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isEnumTypeDefinitionString)(str);
}
static isScalarTypeDefinitionString(str) {
(0, deprecate_1.default)("Use `import { isScalarTypeDefinitionString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isScalarTypeDefinitionString)(str);
}
static isInterfaceTypeDefinitionString(str) {
(0, deprecate_1.default)("Use `import { isInterfaceTypeDefinitionString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isInterfaceTypeDefinitionString)(str);
}
static isUnionTypeDefinitionString(str) {
(0, deprecate_1.default)("Use `import { isUnionTypeDefinitionString } from './utils/typeHelpers'` instead.");
return (0, typeHelpers_1.isUnionTypeDefinitionString)(str);
}
convertGraphQLTypeToComposer(type) {
if (type instanceof graphql_1.GraphQLObjectType) {
return ObjectTypeComposer_1.ObjectTypeComposer.create(type, this.schemaComposer);
}
else if (type instanceof graphql_1.GraphQLInputObjectType) {
return InputTypeComposer_1.InputTypeComposer.create(type, this.schemaComposer);
}
else if (type instanceof graphql_1.GraphQLScalarType) {
return ScalarTypeComposer_1.ScalarTypeComposer.create(type, this.schemaComposer);
}
else if (type instanceof graphql_1.GraphQLEnumType) {
return EnumTypeComposer_1.EnumTypeComposer.create(type, this.schemaComposer);
}
else if (type instanceof graphql_1.GraphQLInterfaceType) {
return InterfaceTypeComposer_1.InterfaceTypeComposer.create(type, this.schemaComposer);
}
else if (type instanceof graphql_1.GraphQLUnionType) {
return UnionTypeComposer_1.UnionTypeComposer.create(type, this.schemaComposer);
}
else if (type instanceof graphql_1.GraphQLNonNull) {
return new NonNullComposer_1.NonNullComposer(this.convertGraphQLTypeToComposer(type.ofType));
}
else if (type instanceof graphql_1.GraphQLList) {
return new ListComposer_1.ListComposer(this.convertGraphQLTypeToComposer(type.ofType));
}
throw new Error(`Cannot convert to Composer the following value: ${(0, misc_2.inspect)(type)}`);
}
convertSDLWrappedTypeName(str) {
const typeAST = (0, parser_1.parseType)(str);
return this.typeFromAST(typeAST);
}
convertSDLTypeDefinition(str) {
if (this.schemaComposer.has(str)) {
return this.schemaComposer.getAnyTC(str);
}
const astDocument = (0, parser_1.parse)(str);
if (!astDocument || astDocument.kind !== language_1.Kind.DOCUMENT) {
throw new Error('You should provide correct type syntax. ' +
"Eg. convertSDLTypeDefinition('type IntRange { min: Int, max: Int }')");
}
const types = this.parseTypes(astDocument);
const type = types[0];
if (type) {
this.schemaComposer.set(type.getTypeName(), type);
this.schemaComposer.set(str, type);
return type;
}
return undefined;
}
convertOutputTypeDefinition(typeDef, fieldName = '', typeName = '') {
if (typeof typeDef === 'string') {
if ((0, typeHelpers_1.isInputTypeDefinitionString)(typeDef)) {
throw new Error(`Should be OutputType, but got input type definition: ${(0, misc_2.inspect)(typeDef)}'`);
}
let tc;
if (this.schemaComposer.has(typeDef)) {
tc = this.schemaComposer.getAnyTC(typeDef);
}
else {
tc = (0, typeHelpers_1.isTypeDefinitionString)(typeDef)
? this.convertSDLTypeDefinition(typeDef)
: this.convertSDLWrappedTypeName(typeDef);
if (!tc) {
throw new Error(`Cannot convert to OutputType the following string: ${(0, misc_2.inspect)(typeDef)}`);
}
}
if (!(0, typeHelpers_1.isSomeOutputTypeComposer)(tc)) {
throw new Error(`Provided incorrect OutputType: ${(0, misc_2.inspect)(typeDef)}`);
}
return tc;
}
else if ((0, typeHelpers_1.isSomeOutputTypeComposer)(typeDef)) {
return typeDef;
}
else if (Array.isArray(typeDef)) {
if (typeDef.length !== 1) {
throw new Error(`Array must have exact one output type definition, but has ${typeDef.length}: ${(0, misc_2.inspect)(typeDef)}`);
}
const tc = this.convertOutputTypeDefinition(typeDef[0], fieldName, typeName);
if (!tc) {
throw new Error(`Cannot construct TypeComposer from ${(0, misc_2.inspect)(typeDef)}`);
}
return new ListComposer_1.ListComposer(tc);
}
else if ((0, is_1.isFunction)(typeDef)) {
return new ThunkComposer_1.ThunkComposer(() => {
const def = typeDef(this.schemaComposer);
const tc = this.convertOutputFieldConfig(def, fieldName, typeName).type;
if (!(0, typeHelpers_1.isSomeOutputTypeComposer)(tc)) {
throw new Error(`Provided incorrect OutputType: Function[${(0, misc_2.inspect)(def)}]`);
}
return tc;
});
}
else if (typeDef instanceof Resolver_1.Resolver) {
return typeDef.getTypeComposer();
}
else if (typeDef instanceof graphql_1.GraphQLList || typeDef instanceof graphql_1.GraphQLNonNull) {
const type = this.convertGraphQLTypeToComposer(typeDef);
if ((0, typeHelpers_1.isSomeOutputTypeComposer)(type)) {
return type;
}
else {
throw new Error(`Provided incorrect OutputType: ${(0, misc_2.inspect)(type)}`);
}
}
else if (typeDef instanceof graphql_1.GraphQLObjectType ||
typeDef instanceof graphql_1.GraphQLEnumType ||
typeDef instanceof graphql_1.GraphQLInterfaceType ||
typeDef instanceof graphql_1.GraphQLUnionType ||
typeDef instanceof graphql_1.GraphQLScalarType) {
return this.convertGraphQLTypeToComposer(typeDef);
}
if (typeDef instanceof InputTypeComposer_1.InputTypeComposer) {
throw new Error(`Should be OutputType, but provided InputTypeComposer ${(0, misc_2.inspect)(typeDef)}`);
}
return undefined;
}
convertOutputFieldConfig(composeFC, fieldName = '', typeName = '') {
var _a, _b, _c, _d;
var _e;
try {
if (!composeFC) {
throw new Error(`You provide empty output field definition: ${(0, misc_2.inspect)(composeFC)}`);
}
if (composeFC instanceof Resolver_1.Resolver) {
return {
type: composeFC.type,
args: composeFC.getArgs(),
resolve: composeFC.getFieldResolver(),
description: composeFC.getDescription(),
extensions: composeFC.extensions,
directives: composeFC.directives || [],
projection: composeFC.projection,
};
}
const tcFromFC = this.convertOutputTypeDefinition(composeFC, fieldName, typeName);
if (tcFromFC) {
return { type: tcFromFC };
}
if ((0, is_1.isObject)(composeFC)) {
const _f = composeFC, { type, args } = _f, rest = __rest(_f, ["type", "args"]);
if (!type) {
throw new Error(`Definition object should contain 'type' property: ${(0, misc_2.inspect)(composeFC)}`);
}
const tc = this.convertOutputTypeDefinition(type, fieldName, typeName);
if (tc) {
const fc = Object.assign({ type: tc, args: this.convertArgConfigMap(args || {}, fieldName, typeName) }, rest);
const deprecatedDirectiveIdx = (_e = (_a = fc === null || fc === void 0 ? void 0 : fc.directives) === null || _a === void 0 ? void 0 : _a.findIndex((d) => d.name === 'deprecated')) !== null && _e !== void 0 ? _e : -1;
if (fc.deprecationReason) {
if (!fc.directives)
fc.directives = [];
if (deprecatedDirectiveIdx >= 0) {
fc.directives[deprecatedDirectiveIdx].args = { reason: fc.deprecationReason };
}
else {
fc.directives.push({ name: 'deprecated', args: { reason: fc.deprecationReason } });
}
}
else if (deprecatedDirectiveIdx >= 0) {
fc.deprecationReason = (_d = (_c = (_b = fc === null || fc === void 0 ? void 0 : fc.directives) === null || _b === void 0 ? void 0 : _b[deprecatedDirectiveIdx]) === null || _c === void 0 ? void 0 : _c.args) === null || _d === void 0 ? void 0 : _d.reason;
}
return fc;
}
}
throw new Error(`Cannot convert to OutputType the following value: ${(0, misc_2.inspect)(composeFC)}`);
}
catch (e) {
e.message = `TypeError[${typeName}.${fieldName}]: ${e.message}`;
throw e;
}
}
convertOutputFieldConfigMap(composeFields, typeName = '') {
const fields = {};
Object.keys(composeFields).forEach((name) => {
fields[name] = this.convertOutputFieldConfig(composeFields[name], name, typeName);
});
return fields;
}
convertArgConfig(composeAC, argName = '', fieldName = '', typeName = '') {
var _a, _b, _c, _d;
var _e;
try {
if (!composeAC) {
throw new Error(`You provide empty argument config ${(0, misc_2.inspect)(composeAC)}`);
}
const tcFromAC = this.convertInputTypeDefinition(composeAC);
if (tcFromAC) {
return { type: tcFromAC };
}
if ((0, is_1.isObject)(composeAC)) {
const _f = composeAC, { type } = _f, rest = __rest(_f, ["type"]);
if (!type) {
throw new Error(`Definition object should contain 'type' property: ${(0, misc_2.inspect)(composeAC)}'`);
}
const tc = this.convertInputTypeDefinition(type);
if (tc) {
const ac = Object.assign({ type: tc }, rest);
const deprecatedDirectiveIdx = (_e = (_a = ac === null || ac === void 0 ? void 0 : ac.directives) === null || _a === void 0 ? void 0 : _a.findIndex((d) => d.name === 'deprecated')) !== null && _e !== void 0 ? _e : -1;
if (ac.deprecationReason) {
if (!ac.directives)
ac.directives = [];
if (deprecatedDirectiveIdx >= 0) {
ac.directives[deprecatedDirectiveIdx].args = { reason: ac.deprecationReason };
}
else {
ac.directives.push({ name: 'deprecated', args: { reason: ac.deprecationReason } });
}
}
else if (deprecatedDirectiveIdx >= 0) {
ac.deprecationReason = (_d = (_c = (_b = ac === null || ac === void 0 ? void 0 : ac.directives) === null || _b === void 0 ? void 0 : _b[deprecatedDirectiveIdx]) === null || _c === void 0 ? void 0 : _c.args) === null || _d === void 0 ? void 0 : _d.reason;
}
return ac;
}
}
throw new Error(`Cannot convert to InputType the following value: ${(0, misc_2.inspect)(tcFromAC)}`);
}
catch (e) {
e.message = `TypeError[${typeName}.${fieldName}.${argName}]: ${e.message}`;
throw e;
}
}
convertArgConfigMap(composeArgsConfigMap, fieldName = '', typeName = '') {
const argsConfigMap = {};
if (composeArgsConfigMap) {
Object.keys(composeArgsConfigMap).forEach((argName) => {
argsConfigMap[argName] = this.convertArgConfig(composeArgsConfigMap[argName], argName, fieldName, typeName);
});
}
return argsConfigMap;
}
convertInputTypeDefinition(typeDef, fieldName = '', typeName = '') {
if (typeof typeDef === 'string') {
if ((0, typeHelpers_1.isOutputTypeDefinitionString)(typeDef)) {
throw new Error(`Should be InputType, but got output type definition: ${(0, misc_2.inspect)(typeDef)}`);
}
let tc;
if (this.schemaComposer.has(typeDef)) {
tc = this.schemaComposer.getAnyTC(typeDef);
}
else {
tc = (0, typeHelpers_1.isTypeDefinitionString)(typeDef)
? this.convertSDLTypeDefinition(typeDef)
: this.convertSDLWrappedTypeName(typeDef);
if (!tc) {
throw new Error(`Cannot convert to InputType the following string: ${(0, misc_2.inspect)(typeDef)}`);
}
}
if (!(0, typeHelpers_1.isSomeInputTypeComposer)(tc)) {
throw new Error(`Provided incorrect InputType: ${(0, misc_2.inspect)(typeDef)}`);
}
return tc;
}
else if ((0, typeHelpers_1.isSomeInputTypeComposer)(typeDef)) {
return typeDef;
}
else if (Array.isArray(typeDef)) {
if (typeDef.length !== 1) {
throw new Error(`Array must have exact one input type definition, but has ${typeDef.length}: ${(0, misc_2.inspect)(typeDef)}`);
}
const tc = this.convertInputTypeDefinition(typeDef[0], fieldName, typeName);
if (!tc) {
throw new Error(`Cannot construct TypeComposer from ${(0, misc_2.inspect)(typeDef)}`);
}
return new ListComposer_1.ListComposer(tc);
}
else if ((0, is_1.isFunction)(typeDef)) {
return new ThunkComposer_1.ThunkComposer(() => {
const def = typeDef(this.schemaComposer);
const tc = this.convertInputFieldConfig(def, fieldName, typeName).type;
if (!(0, typeHelpers_1.isSomeInputTypeComposer)(tc)) {
throw new Error(`Provided incorrect InputType: Function[${(0, misc_2.inspect)(def)}]`);
}
return tc;
});
}
else if (typeDef instanceof graphql_1.GraphQLList || typeDef instanceof graphql_1.GraphQLNonNull) {
const type = this.convertGraphQLTypeToComposer(typeDef);
if ((0, typeHelpers_1.isSomeInputTypeComposer)(type)) {
return type;
}
else {
throw new Error(`Provided incorrect InputType: ${(0, misc_2.inspect)(type)}`);
}
}
else if (typeDef instanceof graphql_1.GraphQLInputObjectType ||
typeDef instanceof graphql_1.GraphQLScalarType ||
typeDef instanceof graphql_1.GraphQLEnumType) {
return this.convertGraphQLTypeToComposer(typeDef);
}
if (typeDef instanceof ObjectTypeComposer_1.ObjectTypeComposer) {
throw new Error(`Should be InputType, but provided ObjectTypeComposer ${(0, misc_2.inspect)(typeDef)}`);
}
return undefined;
}
convertInputFieldConfig(composeIFC, fieldName = '', typeName = '') {
var _a, _b, _c, _d;
var _e;
try {
if (!composeIFC) {
throw new Error(`You provide empty input field definition: ${(0, misc_2.inspect)(composeIFC)}`);
}
const tcFromIFC = this.convertInputTypeDefinition(composeIFC, fieldName, typeName);
if (tcFromIFC) {
return { type: tcFromIFC };
}
if ((0, is_1.isObject)(composeIFC)) {
const _f = composeIFC, { type } = _f, rest = __rest(_f, ["type"]);
if (!type) {
throw new Error(`Definition object should contain 'type' property: ${(0, misc_2.inspect)(composeIFC)}`);
}
const tc = this.convertInputTypeDefinition(type, fieldName, typeName);
if (tc) {
const fc = Object.assign({ type: tc }, rest);
const deprecatedDirectiveIdx = (_e = (_a = fc === null || fc === void 0 ? void 0 : fc.directives) === null || _a === void 0 ? void 0 : _a.findIndex((d) => d.name === 'deprecated')) !== null && _e !== void 0 ? _e : -1;
if (fc.deprecationReason) {
if (!fc.directives)
fc.directives = [];
if (deprecatedDirectiveIdx >= 0) {
fc.directives[deprecatedDirectiveIdx].args = { reason: fc.deprecationReason };
}
else {
fc.directives.push({ name: 'deprecated', args: { reason: fc.deprecationReason } });
}
}
else if (deprecatedDirectiveIdx >= 0) {
fc.deprecationReason = (_d = (_c = (_b = fc === null || fc === void 0 ? void 0 : fc.directives) === null || _b === void 0 ? void 0 : _b[deprecatedDirectiveIdx]) === null || _c === void 0 ? void 0 : _c.args) === null || _d === void 0 ? void 0 : _d.reason;
}
return fc;
}
}
throw new Error(`Cannot convert to InputType the following value: ${(0, misc_2.inspect)(composeIFC)}`);
}
catch (e) {
e.message = `TypeError[${typeName}.${fieldName}]: ${e.message}`;
throw e;
}
}
convertInputFieldConfigMap(composeFields, typeName = '') {
const fields = {};
Object.keys(composeFields).forEach((name) => {
fields[name] = this.convertInputFieldConfig(composeFields[name], name, typeName);
});
return fields;
}
convertInterfaceTypeDefinition(typeDef) {
if (this.schemaComposer.hasInstance(typeDef, InterfaceTypeComposer_1.InterfaceTypeComposer)) {
return this.schemaComposer.getIFTC(typeDef);
}
else if (typeof typeDef === 'string') {
const tc = (0, typeHelpers_1.isInterfaceTypeDefinitionString)(typeDef)
? this.convertSDLTypeDefinition(typeDef)
: this.convertSDLWrappedTypeName(typeDef);
if (!(tc instanceof InterfaceTypeComposer_1.InterfaceTypeComposer) && !(tc instanceof ThunkComposer_1.ThunkComposer)) {
throw new Error(`Cannot convert to InterfaceType the following definition: ${(0, misc_2.inspect)(typeDef)}`);
}
return tc;
}
else if (typeDef instanceof graphql_1.GraphQLInterfaceType) {
return new InterfaceTypeComposer_1.InterfaceTypeComposer(typeDef, this.schemaComposer);
}
else if (typeDef instanceof InterfaceTypeComposer_1.InterfaceTypeComposer || typeDef instanceof ThunkComposer_1.ThunkComposer) {
return typeDef;
}
else if ((0, is_1.isFunction)(typeDef)) {
return new ThunkComposer_1.ThunkComposer(() => this.convertInterfaceTypeDefinition(typeDef(this.schemaComposer)));
}
throw new Error(`Cannot convert to InterfaceType the following definition: ${(0, misc_2.inspect)(typeDef)}`);
}
parseTypesFromString(str) {
const source = new language_1.Source(str);
source.name = 'GraphQL SDL';
const astDocument = (0, parser_1.parse)(source);
if (!astDocument || astDocument.kind !== 'Document') {
throw new Error('You should provide correct SDL syntax.');
}
const types = this.parseTypes(astDocument);
const typeStorage = new TypeStorage_1.TypeStorage();
types.forEach((type) => {
typeStorage.set(type.getTypeName(), type);
});
return typeStorage;
}
parseTypes(astDocument) {
const types = [];
for (let i = 0; i < astDocument.definitions.length; i++) {
const def = astDocument.definitions[i];
const type = this.makeSchemaDef(def);
if (type) {
types[i] = type;
}
}
return types;
}
typeFromAST(typeNode) {
if (typeNode.kind === language_1.Kind.LIST_TYPE) {
return new ListComposer_1.ListComposer(this.typeFromAST(typeNode.type));
}
else if (typeNode.kind === language_1.Kind.NON_NULL_TYPE) {
return new NonNullComposer_1.NonNullComposer(this.typeFromAST(typeNode.type));
}
(0, misc_1.invariant)(typeNode.kind === language_1.Kind.NAMED_TYPE, `Must be a named type for ${(0, misc_2.inspect)(typeNode)}.`);
const typeName = typeNode.name.value;
if (this.schemaComposer.has(typeName)) {
return this.schemaComposer.get(typeName);
}
const st = this.getBuiltInType(typeName);
if (st)
return st;
return new ThunkComposer_1.ThunkComposer(() => {
return this.schemaComposer.get(typeName);
}, typeName);
}
typeFromASTInput(typeNode) {
const tc = this.typeFromAST(typeNode);
if (!(0, typeHelpers_1.isSomeInputTypeComposer)(tc)) {
throw new Error(`TypeAST should be for Input types. But received ${(0, misc_2.inspect)(typeNode)}`);
}
return tc;
}
typeFromASTOutput(typeNode) {
const tc = this.typeFromAST(typeNode);
if (!(0, typeHelpers_1.isSomeOutputTypeComposer)(tc)) {
throw new Error(`TypeAST should be for Output types. But received ${(0, misc_2.inspect)(typeNode)}`);
}
return tc;
}
makeSchemaDef(def) {
if (!def) {
throw new Error('def must be defined');
}
switch (def.kind) {
case language_1.Kind.OBJECT_TYPE_DEFINITION:
return this.makeTypeDef(def);
case language_1.Kind.INTERFACE_TYPE_DEFINITION:
return this.makeInterfaceDef(def);
case language_1.Kind.ENUM_TYPE_DEFINITION:
return this.makeEnumDef(def);
case language_1.Kind.UNION_TYPE_DEFINITION:
return this.makeUnionDef(def);
case language_1.Kind.SCALAR_TYPE_DEFINITION:
return this.makeScalarDef(def);
case language_1.Kind.SCHEMA_DEFINITION:
this.checkSchemaDef(def);
return null;
case language_1.Kind.DIRECTIVE_DEFINITION: {
const directive = this.makeDirectiveDef(def);
if (directive)
this.schemaComposer.addDirective(directive);
return null;
}
case language_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
return this.makeInputObjectDef(def);
case language_1.Kind.OBJECT_TYPE_EXTENSION:
return this.makeExtendTypeDef(def);
case language_1.Kind.INPUT_OBJECT_TYPE_EXTENSION:
return this.makeExtendInputObjectDef(def);
case language_1.Kind.INTERFACE_TYPE_EXTENSION:
return this.makeExtendInterfaceDef(def);
case language_1.Kind.UNION_TYPE_EXTENSION:
return this.makeExtendUnionDef(def);
case language_1.Kind.ENUM_TYPE_EXTENSION:
return this.makeExtendEnumDef(def);
case language_1.Kind.SCALAR_TYPE_EXTENSION:
return this.makeExtendScalarDef(def);
default:
throw new Error(`Type kind "${def.kind}" not supported.`);
}
}
makeArguments(values) {
if (!values) {
return {};
}
const result = {};
values.forEach((value) => {
var _a;
const key = value.name.value;
const typeName = this.getNamedTypeAST(value.type).name.value;
const type = this.typeFromASTInput(value.type);
const ac = {
type,
description: getDescription(value),
directives: this.parseDirectives(value.directives),
deprecationReason: this.getDeprecationReason(value.directives),
astNode: value,
};
if (value.defaultValue) {
if (!this.schemaComposer.has(typeName) && ((_a = value === null || value === void 0 ? void 0 : value.defaultValue) === null || _a === void 0 ? void 0 : _a.value)) {
ac.defaultValue = value.defaultValue.value;
}
else {
const typeDef = this.schemaComposer.get(typeName);
const wrappedType = this.buildWrappedTypeDef(typeDef, value.type);
if ((0, typeHelpers_1.isSomeInputTypeComposer)(wrappedType)) {
ac.defaultValue = (0, graphql_1.valueFromAST)(value.defaultValue, wrappedType.getType());
}
else {
throw new Error('Non-input type as an argument.');
}
}
}
result[key] = ac;
});
return result;
}
makeFieldDefMap(def) {
if (!def.fields)
return {};
return (0, misc_2.keyValMap)(def.fields, (field) => field.name.value, (field) => {
const fc = {
type: this.typeFromASTOutput(field.type),
description: getDescription(field),
args: this.makeArguments(field.arguments),
deprecationReason: this.getDeprecationReason(field.directives),
astNode: field,
directives: this.parseDirectives(field.directives),
};
return fc;
});
}
makeInputFieldDef(def) {
if (!def.fields)
return {};
return (0, misc_2.keyValMap)(def.fields, (field) => field.name.value, (field) => {
const fc = {
type: this.typeFromASTInput(field.type),
description: getDescription(field),
deprecationReason: this.getDeprecationReason(field.directives),
astNode: field,
directives: this.parseDirectives(field.directives),
};
if (field.defaultValue) {
fc.defaultValue = (0, graphql_1.valueFromAST)(field.defaultValue, fc.type.getType());
}
return fc;
});
}
makeEnumDef(def) {
const tc = this.schemaComposer.createEnumTC({
name: def.name.value,
description: getDescription(def),
values: this.makeEnumValuesDef(def),
directives: this.parseDirectives(def.directives),
astNode: def,
});
return tc;
}
makeEnumValuesDef(def) {
if (!def.values)
return {};
return (0, misc_2.keyValMap)(def.values, (enumValue) => enumValue.name.value, (enumValue) => {
const ec = {
description: getDescription(enumValue),
deprecationReason: this.getDeprecationReason(enumValue.directives),
directives: this.parseDirectives(enumValue.directives),
};
return ec;
});
}
makeInputObjectDef(def) {
const tc = this.schemaComposer.createInputTC({
name: def.name.value,
description: getDescription(def),
fields: this.makeInputFieldDef(def),
astNode: def,
directives: this.parseDirectives(def.directives),
});
return tc;
}
makeDirectiveDef(def) {
const locations = def.locations.map(({ value }) => value);
const args = {};
(def.arguments || []).forEach((value) => {
const key = value.name.value;
let val;
const wrappedType = this.typeFromAST(value.type);
if ((0, typeHelpers_1.isSomeInputTypeComposer)(wrappedType)) {
val = {
type: wrappedType.getType(),
description: getDescription(value),
defaultValue: (0, graphql_1.valueFromAST)(value.defaultValue, wrappedType.getType()),
};
}
else {
throw new Error('Non-input type as an argument.');
}
args[key] = val;
});
return new graphql_1.GraphQLDirective({
name: def.name.value,
description: getDescription(def),
locations,
args,
astNode: def,
});
}
getBuiltInType(name) {
let type;
switch (name) {
case 'String':
type = graphql_1.GraphQLString;
break;
case 'Float':
type = graphql_1.GraphQLFloat;
break;
case 'Int':
type = graphql_1.GraphQLInt;
break;
case 'Boolean':
type = graphql_1.GraphQLBoolean;
break;
case 'ID':
type = graphql_1.GraphQLID;
break;
case 'JSON':
type = type_1.GraphQLJSON;
break;
case 'JSONObject':
type = type_1.GraphQLJSONObject;
break;
case 'Date':
type = type_1.GraphQLDate;
break;
case 'Buffer':
type = type_1.GraphQLBuffer;
break;
default:
type = undefined;
break;
}
if (type) {
return this.schemaComposer.createScalarTC(type);
}
return undefined;
}
makeScalarDef(def) {
let tc;
const stc = this.getBuiltInType(def.name.value);
if (stc) {
tc = stc;
}
if (!tc) {
tc = this.schemaComposer.createScalarTC({
name: def.name.value,
description: getDescription(def),
serialize: (v) => v,
astNode: def,
});
}
if (def.directives) {
tc.setDirectives(this.parseDirectives(def.directives));
}
return tc;
}
makeImplementedInterfaces(def) {
return (def.interfaces || []).map((iface) => {
const name = this.getNamedTypeAST(iface).name.value;
if (this.schemaComposer.hasInstance(name, InterfaceTypeComposer_1.InterfaceTypeComposer)) {
return this.schemaComposer.getIFTC(name);
}
else {
return new ThunkComposer_1.ThunkComposer(() => this.schemaComposer.getIFTC(name), name);
}
});
}
makeTypeDef(def) {
const name = def.name.value;
const tc = this.schemaComposer.createObjectTC({
name,
description: getDescription(def),
fields: this.makeFieldDefMap(def),
interfaces: this.makeImplementedInterfaces(def),
astNode: def,
directives: this.parseDirectives(def.directives),
});
return tc;
}
makeInterfaceDef(def) {
const tc = this.schemaComposer.createInterfaceTC({
name: def.name.value,
description: getDescription(def),
fields: this.makeFieldDefMap(def),
interfaces: this.makeImplementedInterfaces(def),
astNode: def,
directives: this.parseDirectives(def.directives),
});
return tc;
}
makeUnionDef(def) {
const types = def.types;
const tc = this.schemaComposer.createUnionTC({
name: def.name.value,
description: getDescription(def),
types: (types || []).map((ref) => this.getNamedTypeAST(ref).name.value),
astNode: def,
});
if (def.directives) {
tc.setDirectives(this.parseDirectives(def.directives));
}
return tc;
}
checkSchemaDef(def) {
const validNames = {
query: 'Query',
mutation: 'Mutation',
subscription: 'Subscription',
};
def.operationTypes.forEach((d) => {
if (d.operation) {
const validTypeName = validNames[d.operation];
const actualTypeName = d.type.name.value;
if (actualTypeName !== validTypeName) {
throw new Error(`Incorrect type name '${actualTypeName}' for '${d.operation}'. The valid definition is "schema { ${d.operation}: ${validTypeName} }"`);
}
}
});
}
getNamedTypeAST(typeAST) {
let namedType = typeAST;
while (namedType.kind === language_1.Kind.LIST_TYPE || namedType.kind === language_1.Kind.NON_NULL_TYPE) {
namedType = namedType.type;
}
return namedType;
}
buildWrappedTypeDef(innerType, inputTypeAST) {
if (inputTypeAST.kind === language_1.Kind.LIST_TYPE) {
return new ListComposer_1.ListComposer(this.buildWrappedTypeDef(innerType, inputTypeAST.type));
}
if (inputTypeAST.kind === language_1.Kind.NON_NULL_TYPE) {
const wrappedType = this.buildWrappedTypeDef(innerType, inputTypeAST.type);
return new NonNullComposer_1.NonNullComposer(wrappedType);
}
return innerType;
}
getDeprecationReason(directives) {
const deprecatedAST = directives === null || directives === void 0 ? void 0 : directives.find((directive) => directive.name.value === graphql_1.GraphQLDeprecatedDirective.name);
if (!deprecatedAST) {
return;
}
const { reason } = (0, values_1.getArgumentValues)(graphql_1.GraphQLDeprecatedDirective, deprecatedAST);
return reason;
}
parseDirectives(directives) {
const result = [];
if (!directives)
return result;
directives.forEach((directive) => {
const name = directive.name.value;
const directiveDef = this.schemaComposer._getDirective(name);
const args = directiveDef
? (0, values_1.getArgumentValues)(directiveDef, directive)
: (0, misc_2.keyValMap)(directive.arguments || [], (arg) => arg.name.value, (arg) => (0, definitionNode_1.parseValueNode)(arg.value));
result.push({ name, args });
});
return result;
}
makeExtendTypeDef(def) {
const tc = this.schemaComposer.getOrCreateOTC(def.name.value);
tc.addInterfaces(this.makeImplementedInterfaces(def));
tc.addFields(this.makeFieldDefMap(def));
if (def.directives) {
tc.setDirectives([...tc.getDirectives(), ...this.parseDirectives(def.directives)]);
}
return tc;
}
makeExtendInputObjectDef(def) {
const tc = this.schemaComposer.getOrCreateITC(def.name.value);
tc.addFields(this.makeInputFieldDef(def));
if (def.directives) {
tc.setDirectives([...tc.getDirectives(), ...this.parseDirectives(def.directives)]);
}
return tc;
}
makeExtendInterfaceDef(def) {
const tc = this.schemaComposer.getOrCreateIFTC(def.name.value);
tc.addFields(this.makeFieldDefMap(def));
if (def.directives) {
tc.setDirectives([...tc.getDirectives(), ...this.parseDirectives(def.directives)]);
}
return tc;
}
makeExtendUnionDef(def) {
const types = def.types;
const tc = this.schemaComposer.getOrCreateUTC(def.name.value);
tc.addTypes((types || []).map((ref) => this.getNamedTypeAST(ref).name.value));
if (def.directives) {
tc.setDirectives([...tc.getDirectives(), ...this.parseDirectives(def.directives)]);
}
return tc;
}
makeExtendEnumDef(def) {
const tc = this.schemaComposer.getOrCreateETC(def.name.value);
tc.addFields(this.makeEnumValuesDef(def));
if (def.directives) {
tc.setDirectives([...tc.getDirectives(), ...this.parseDirectives(def.directives)]);
}
return tc;
}
makeExtendScalarDef(def) {
const tc = this.schemaComposer.getSTC(def.name.value);
if (def.directives) {
tc.setDirectives([...tc.getDirectives(), ...this.parseDirectives(def.directives)]);
}
return tc;
}
}
exports.TypeMapper = TypeMapper;
function getDescription(node, options) {
if (node.description) {
return node.description.value;
}
if ((options === null || options === void 0 ? void 0 : options.commentDescriptions) === true) {
const rawValue = getLeadingCommentBlock(node);
if (rawValue !== undefined) {
if (!blockString_1.dedentBlockStringValue) {
return undefined;
}
else {
return (0, blockString_1.dedentBlockStringValue)('\n' + rawValue);
}
}
}
return undefined;
}
function getLeadingCommentBlock(node) {
const loc = node.loc;
if (!loc) {
return;
}
const comments = [];
let token = loc.startToken.prev;
while (token != null &&
token.kind === language_1.TokenKind.COMMENT &&
token.next &&
token.prev &&
token.line + 1 === token.next.line &&
token.line !== token.prev.line) {
const value = String(token.value);
comments.push(value);
token = token.prev;
}
return comments.length > 0 ? comments.reverse().join('\n') : undefined;
}
//# sourceMappingURL=TypeMapper.js.map