graphql-compose
Version:
GraphQL schema builder from different data sources with middleware extensions.
1,099 lines • 47.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InterfaceTypeComposer = void 0;
const graphql_1 = require("./graphql");
const is_1 = require("./utils/is");
const misc_1 = require("./utils/misc");
const ObjectTypeComposer_1 = require("./ObjectTypeComposer");
const InputTypeComposer_1 = require("./InputTypeComposer");
const UnionTypeComposer_1 = require("./UnionTypeComposer");
const EnumTypeComposer_1 = require("./EnumTypeComposer");
const SchemaComposer_1 = require("./SchemaComposer");
const ListComposer_1 = require("./ListComposer");
const NonNullComposer_1 = require("./NonNullComposer");
const ThunkComposer_1 = require("./ThunkComposer");
const toInputType_1 = require("./utils/toInputType");
const typeByPath_1 = require("./utils/typeByPath");
const typeHelpers_1 = require("./utils/typeHelpers");
const configToDefine_1 = require("./utils/configToDefine");
const graphqlVersion_1 = require("./utils/graphqlVersion");
const schemaPrinter_1 = require("./utils/schemaPrinter");
const definitionNode_1 = require("./utils/definitionNode");
const schemaPrinterSortTypes_1 = require("./utils/schemaPrinterSortTypes");
class InterfaceTypeComposer {
static create(typeDef, schemaComposer) {
if (!(schemaComposer instanceof SchemaComposer_1.SchemaComposer)) {
throw new Error('You must provide SchemaComposer instance as a second argument for `InterfaceTypeComposer.create(typeDef, schemaComposer)`');
}
if (schemaComposer.hasInstance(typeDef, InterfaceTypeComposer)) {
return schemaComposer.getIFTC(typeDef);
}
const iftc = this.createTemp(typeDef, schemaComposer);
schemaComposer.add(iftc);
return iftc;
}
static createTemp(typeDef, schemaComposer) {
const sc = schemaComposer || new SchemaComposer_1.SchemaComposer();
let IFTC;
if ((0, is_1.isString)(typeDef)) {
const typeName = typeDef;
if ((0, typeHelpers_1.isTypeNameString)(typeName)) {
IFTC = new InterfaceTypeComposer(new graphql_1.GraphQLInterfaceType({
name: typeName,
fields: () => ({}),
}), sc);
}
else {
IFTC = sc.typeMapper.convertSDLTypeDefinition(typeName);
if (!(IFTC instanceof InterfaceTypeComposer)) {
throw new Error('You should provide correct GraphQLInterfaceType type definition. ' +
'Eg. `interface MyType { id: ID!, name: String! }`');
}
}
}
else if (typeDef instanceof graphql_1.GraphQLInterfaceType) {
IFTC = new InterfaceTypeComposer(typeDef, sc);
}
else if (typeDef instanceof InterfaceTypeComposer) {
IFTC = typeDef;
}
else if ((0, is_1.isObject)(typeDef) && !(typeDef instanceof InterfaceTypeComposer)) {
const type = new graphql_1.GraphQLInterfaceType(Object.assign(Object.assign({}, typeDef), { fields: () => ({}) }));
IFTC = new InterfaceTypeComposer(type, sc);
const fields = typeDef.fields;
if ((0, is_1.isFunction)(fields)) {
IFTC.addFields((0, configToDefine_1.convertObjectFieldMapToConfig)(fields, sc));
}
else if ((0, is_1.isObject)(fields)) {
IFTC.addFields(fields);
}
const interfaces = typeDef.interfaces;
if (Array.isArray(interfaces))
IFTC.setInterfaces(interfaces);
else if ((0, is_1.isFunction)(interfaces)) {
IFTC.setInterfaces((0, configToDefine_1.convertInterfaceArrayAsThunk)(interfaces, sc));
}
IFTC.setExtensions(typeDef.extensions);
if (Array.isArray(typeDef === null || typeDef === void 0 ? void 0 : typeDef.directives)) {
IFTC.setDirectives(typeDef.directives);
}
}
else {
throw new Error(`You should provide GraphQLInterfaceTypeConfig or string with interface name or SDL definition. Provided:\n${(0, misc_1.inspect)(typeDef)}`);
}
return IFTC;
}
constructor(graphqlType, schemaComposer) {
this._gqcInterfaces = [];
this._gqcFallbackResolveType = null;
if (!(schemaComposer instanceof SchemaComposer_1.SchemaComposer)) {
throw new Error('You must provide SchemaComposer instance as a second argument for `new InterfaceTypeComposer(GraphQLInterfaceType, SchemaComposer)`');
}
if (!(graphqlType instanceof graphql_1.GraphQLInterfaceType)) {
throw new Error('InterfaceTypeComposer accept only GraphQLInterfaceType in constructor');
}
this.schemaComposer = schemaComposer;
this._gqType = graphqlType;
this.schemaComposer.set(graphqlType, this);
this.schemaComposer.set(graphqlType.name, this);
if (graphqlVersion_1.graphqlVersion >= 15) {
this._gqcFields = (0, configToDefine_1.convertObjectFieldMapToConfig)(this._gqType._fields, this.schemaComposer);
this._gqcInterfaces = (0, configToDefine_1.convertInterfaceArrayAsThunk)(this._gqType._interfaces, this.schemaComposer);
}
else if (graphqlVersion_1.graphqlVersion >= 14) {
this._gqcFields = (0, configToDefine_1.convertObjectFieldMapToConfig)(this._gqType._fields, this.schemaComposer);
}
else {
const fields = this._gqType._typeConfig
.fields;
this._gqcFields = this.schemaComposer.typeMapper.convertOutputFieldConfigMap((0, misc_1.resolveMaybeThunk)(fields) || {}, this.getTypeName());
}
if (!this._gqType.astNode) {
this._gqType.astNode = (0, definitionNode_1.getInterfaceTypeDefinitionNode)(this);
}
this._gqcIsModified = false;
}
getFields() {
return this._gqcFields;
}
getFieldNames() {
return Object.keys(this._gqcFields);
}
getField(fieldName) {
if ((0, is_1.isFunction)(this._gqcFields[fieldName])) {
const unwrappedFieldConfig = this._gqcFields[fieldName](this.schemaComposer);
this.setField(fieldName, unwrappedFieldConfig);
}
const field = this._gqcFields[fieldName];
if (!field) {
throw new Error(`Cannot get field '${fieldName}' from type '${this.getTypeName()}'. Field does not exist.`);
}
return field;
}
hasField(fieldName) {
return !!this._gqcFields[fieldName];
}
setFields(fields) {
this._gqcFields = {};
Object.keys(fields).forEach((name) => {
this.setField(name, fields[name]);
});
return this;
}
setField(fieldName, fieldConfig) {
this._gqcFields[fieldName] = (0, is_1.isFunction)(fieldConfig)
? fieldConfig
: this.schemaComposer.typeMapper.convertOutputFieldConfig(fieldConfig, fieldName, this.getTypeName());
this._gqcIsModified = true;
return this;
}
addFields(newFields) {
Object.keys(newFields).forEach((name) => {
this.setField(name, newFields[name]);
});
return this;
}
removeField(fieldNameOrArray) {
const fieldNames = Array.isArray(fieldNameOrArray) ? fieldNameOrArray : [fieldNameOrArray];
fieldNames.forEach((fieldName) => {
const names = fieldName.split('.');
const name = names.shift();
if (!name)
return;
if (names.length === 0) {
delete this._gqcFields[name];
this._gqcIsModified = true;
}
else {
if (this.hasField(name)) {
const subTC = this.getFieldTC(name);
if (subTC instanceof ObjectTypeComposer_1.ObjectTypeComposer || subTC instanceof EnumTypeComposer_1.EnumTypeComposer) {
subTC.removeField(names.join('.'));
}
}
}
});
return this;
}
removeOtherFields(fieldNameOrArray) {
const keepFieldNames = Array.isArray(fieldNameOrArray) ? fieldNameOrArray : [fieldNameOrArray];
Object.keys(this._gqcFields).forEach((fieldName) => {
if (keepFieldNames.indexOf(fieldName) === -1) {
delete this._gqcFields[fieldName];
this._gqcIsModified = true;
}
});
return this;
}
reorderFields(names) {
const orderedFields = {};
const fields = this._gqcFields;
names.forEach((name) => {
if (fields[name]) {
orderedFields[name] = fields[name];
delete fields[name];
}
});
this._gqcFields = Object.assign(Object.assign({}, orderedFields), fields);
this._gqcIsModified = true;
return this;
}
extendField(fieldName, partialFieldConfig) {
let prevFieldConfig;
try {
prevFieldConfig = this.getField(fieldName);
}
catch (e) {
throw new Error(`Cannot extend field '${fieldName}' from type '${this.getTypeName()}'. Field does not exist.`);
}
this.setField(fieldName, Object.assign(Object.assign(Object.assign({}, prevFieldConfig), partialFieldConfig), { extensions: Object.assign(Object.assign({}, (prevFieldConfig.extensions || {})), (partialFieldConfig.extensions || {})), directives: [...(prevFieldConfig.directives || []), ...(partialFieldConfig.directives || [])] }));
return this;
}
getFieldConfig(fieldName) {
const _a = this.getField(fieldName), { type, args } = _a, rest = __rest(_a, ["type", "args"]);
return Object.assign({ type: type.getType(), args: args &&
(0, misc_1.mapEachKey)(args, (ac) => (Object.assign(Object.assign({}, ac), { type: ac.type.getType() }))) }, rest);
}
getFieldType(fieldName) {
return this.getField(fieldName).type.getType();
}
getFieldTypeName(fieldName) {
return this.getField(fieldName).type.getTypeName();
}
getFieldTC(fieldName) {
const anyTC = this.getField(fieldName).type;
return (0, typeHelpers_1.unwrapOutputTC)(anyTC);
}
getFieldOTC(fieldName) {
const tc = this.getFieldTC(fieldName);
if (!(tc instanceof ObjectTypeComposer_1.ObjectTypeComposer)) {
throw new Error(`${this.getTypeName()}.getFieldOTC('${fieldName}') must be ObjectTypeComposer, but received ${tc.constructor.name}. Maybe you need to use 'getFieldTC()' method which returns any type composer?`);
}
return tc;
}
isFieldNonNull(fieldName) {
return this.getField(fieldName).type instanceof NonNullComposer_1.NonNullComposer;
}
makeFieldNonNull(fieldNameOrArray) {
const fieldNames = Array.isArray(fieldNameOrArray) ? fieldNameOrArray : [fieldNameOrArray];
fieldNames.forEach((fieldName) => {
const fc = this._gqcFields[fieldName];
if (fc && !(fc.type instanceof NonNullComposer_1.NonNullComposer)) {
fc.type = new NonNullComposer_1.NonNullComposer(fc.type);
this._gqcIsModified = true;
}
});
return this;
}
makeFieldNullable(fieldNameOrArray) {
const fieldNames = Array.isArray(fieldNameOrArray) ? fieldNameOrArray : [fieldNameOrArray];
fieldNames.forEach((fieldName) => {
const fc = this._gqcFields[fieldName];
if (fc && fc.type instanceof NonNullComposer_1.NonNullComposer) {
fc.type = fc.type.ofType;
this._gqcIsModified = true;
}
});
return this;
}
isFieldPlural(fieldName) {
const type = this.getField(fieldName).type;
return (type instanceof ListComposer_1.ListComposer ||
(type instanceof NonNullComposer_1.NonNullComposer && type.ofType instanceof ListComposer_1.ListComposer));
}
makeFieldPlural(fieldNameOrArray) {
const fieldNames = Array.isArray(fieldNameOrArray) ? fieldNameOrArray : [fieldNameOrArray];
fieldNames.forEach((fieldName) => {
const fc = this._gqcFields[fieldName];
if (fc && !(fc.type instanceof ListComposer_1.ListComposer)) {
fc.type = new ListComposer_1.ListComposer(fc.type);
this._gqcIsModified = true;
}
});
return this;
}
makeFieldNonPlural(fieldNameOrArray) {
const fieldNames = Array.isArray(fieldNameOrArray) ? fieldNameOrArray : [fieldNameOrArray];
fieldNames.forEach((fieldName) => {
const fc = this._gqcFields[fieldName];
if (fc) {
if (fc.type instanceof ListComposer_1.ListComposer) {
fc.type = fc.type.ofType;
this._gqcIsModified = true;
}
else if (fc.type instanceof NonNullComposer_1.NonNullComposer && fc.type.ofType instanceof ListComposer_1.ListComposer) {
fc.type =
fc.type.ofType.ofType instanceof NonNullComposer_1.NonNullComposer
? fc.type.ofType.ofType
: new NonNullComposer_1.NonNullComposer(fc.type.ofType.ofType);
this._gqcIsModified = true;
}
}
});
return this;
}
deprecateFields(fields) {
const existedFieldNames = this.getFieldNames();
if (typeof fields === 'string') {
if (existedFieldNames.indexOf(fields) === -1) {
throw new Error(`Cannot deprecate non-existent field '${fields}' from interface type '${this.getTypeName()}'`);
}
this.extendField(fields, { deprecationReason: 'deprecated' });
}
else if (Array.isArray(fields)) {
fields.forEach((field) => {
if (existedFieldNames.indexOf(field) === -1) {
throw new Error(`Cannot deprecate non-existent field '${field}' from interface type '${this.getTypeName()}'`);
}
this.extendField(field, { deprecationReason: 'deprecated' });
});
}
else {
const fieldMap = fields;
Object.keys(fieldMap).forEach((field) => {
if (existedFieldNames.indexOf(field) === -1) {
throw new Error(`Cannot deprecate non-existent field '${field}' from interface type '${this.getTypeName()}'`);
}
const deprecationReason = fieldMap[field];
this.extendField(field, { deprecationReason });
});
}
return this;
}
getFieldArgs(fieldName) {
try {
const fc = this.getField(fieldName);
return fc.args || {};
}
catch (e) {
throw new Error(`Cannot get field args. Field '${fieldName}' from type '${this.getTypeName()}' does not exist.`);
}
}
getFieldArgNames(fieldName) {
return Object.keys(this.getFieldArgs(fieldName));
}
hasFieldArg(fieldName, argName) {
try {
const fieldArgs = this.getFieldArgs(fieldName);
return !!fieldArgs[argName];
}
catch (e) {
return false;
}
}
getFieldArg(fieldName, argName) {
const fieldArgs = this.getFieldArgs(fieldName);
const arg = fieldArgs[argName];
if (!arg) {
throw new Error(`Cannot get '${this.getTypeName()}.${fieldName}@${argName}'. Argument does not exist.`);
}
return arg;
}
getFieldArgType(fieldName, argName) {
const ac = this.getFieldArg(fieldName, argName);
return ac.type.getType();
}
getFieldArgTypeName(fieldName, argName) {
const ac = this.getFieldArg(fieldName, argName);
return ac.type.getTypeName();
}
getFieldArgTC(fieldName, argName) {
const anyTC = this.getFieldArg(fieldName, argName).type;
return (0, typeHelpers_1.unwrapInputTC)(anyTC);
}
getFieldArgITC(fieldName, argName) {
const tc = this.getFieldArgTC(fieldName, argName);
if (!(tc instanceof InputTypeComposer_1.InputTypeComposer)) {
throw new Error(`${this.getTypeName()}.getFieldArgITC('${fieldName}', '${argName}') must be InputTypeComposer, but received ${tc.constructor.name}. Maybe you need to use 'getFieldArgTC()' method which returns any type composer?`);
}
return tc;
}
setFieldArgs(fieldName, args) {
const fc = this.getField(fieldName);
fc.args = this.schemaComposer.typeMapper.convertArgConfigMap(args, fieldName, this.getTypeName());
this._gqcIsModified = true;
return this;
}
addFieldArgs(fieldName, newArgs) {
const fc = this.getField(fieldName);
fc.args = Object.assign(Object.assign({}, fc.args), this.schemaComposer.typeMapper.convertArgConfigMap(newArgs, fieldName, this.getTypeName()));
this._gqcIsModified = true;
return this;
}
setFieldArg(fieldName, argName, argConfig) {
const fc = this.getField(fieldName);
fc.args = fc.args || {};
fc.args[argName] = this.schemaComposer.typeMapper.convertArgConfig(argConfig, argName, fieldName, this.getTypeName());
this._gqcIsModified = true;
return this;
}
isFieldArgPlural(fieldName, argName) {
const type = this.getFieldArg(fieldName, argName).type;
return (type instanceof ListComposer_1.ListComposer ||
(type instanceof NonNullComposer_1.NonNullComposer && type.ofType instanceof ListComposer_1.ListComposer));
}
makeFieldArgPlural(fieldName, argNameOrArray) {
const args = this.getField(fieldName).args;
if (!args)
return this;
const argNames = Array.isArray(argNameOrArray) ? argNameOrArray : [argNameOrArray];
argNames.forEach((argName) => {
const ac = args[argName];
if (ac && !(ac.type instanceof ListComposer_1.ListComposer)) {
ac.type = new ListComposer_1.ListComposer(ac.type);
this._gqcIsModified = true;
}
});
return this;
}
makeFieldArgNonPlural(fieldName, argNameOrArray) {
const args = this.getField(fieldName).args;
if (!args)
return this;
const argNames = Array.isArray(argNameOrArray) ? argNameOrArray : [argNameOrArray];
argNames.forEach((argName) => {
const ac = args[argName];
if (ac) {
if (ac.type instanceof ListComposer_1.ListComposer) {
ac.type = ac.type.ofType;
this._gqcIsModified = true;
}
else if (ac.type instanceof NonNullComposer_1.NonNullComposer && ac.type.ofType instanceof ListComposer_1.ListComposer) {
ac.type =
ac.type.ofType.ofType instanceof NonNullComposer_1.NonNullComposer
? ac.type.ofType.ofType
: new NonNullComposer_1.NonNullComposer(ac.type.ofType.ofType);
this._gqcIsModified = true;
}
}
});
return this;
}
isFieldArgNonNull(fieldName, argName) {
const type = this.getFieldArg(fieldName, argName).type;
return type instanceof NonNullComposer_1.NonNullComposer;
}
makeFieldArgNonNull(fieldName, argNameOrArray) {
const args = this.getField(fieldName).args;
if (!args)
return this;
const argNames = Array.isArray(argNameOrArray) ? argNameOrArray : [argNameOrArray];
argNames.forEach((argName) => {
const ac = args[argName];
if (ac && !(ac.type instanceof NonNullComposer_1.NonNullComposer)) {
ac.type = new NonNullComposer_1.NonNullComposer(ac.type);
this._gqcIsModified = true;
}
});
return this;
}
makeFieldArgNullable(fieldName, argNameOrArray) {
const args = this.getField(fieldName).args;
if (!args)
return this;
const argNames = Array.isArray(argNameOrArray) ? argNameOrArray : [argNameOrArray];
argNames.forEach((argName) => {
const ac = args[argName];
if (ac && ac.type instanceof NonNullComposer_1.NonNullComposer) {
ac.type = ac.type.ofType;
this._gqcIsModified = true;
}
});
return this;
}
getType() {
if (this._gqcIsModified) {
this._gqcIsModified = false;
this._gqType.astNode = (0, definitionNode_1.getInterfaceTypeDefinitionNode)(this);
if (graphqlVersion_1.graphqlVersion >= 15) {
this._gqType._fields = () => (0, configToDefine_1.defineFieldMap)(this._gqType, (0, misc_1.mapEachKey)(this._gqcFields, (_, name) => this.getFieldConfig(name)), this._gqType.astNode);
this._gqType._interfaces = () => this.getInterfacesTypes();
}
else if (graphqlVersion_1.graphqlVersion >= 14) {
this._gqType._fields = () => (0, configToDefine_1.defineFieldMap)(this._gqType, (0, misc_1.mapEachKey)(this._gqcFields, (_, name) => this.getFieldConfig(name)), this._gqType.astNode);
}
else {
this._gqType._typeConfig.fields = () => {
return (0, misc_1.mapEachKey)(this._gqcFields, (_, name) => this.getFieldConfig(name));
};
this._gqType._fields = {};
}
}
return this._gqType;
}
getTypePlural() {
return new ListComposer_1.ListComposer(this);
}
getTypeNonNull() {
return new NonNullComposer_1.NonNullComposer(this);
}
get List() {
return new ListComposer_1.ListComposer(this);
}
get NonNull() {
return new NonNullComposer_1.NonNullComposer(this);
}
getTypeName() {
return this._gqType.name;
}
setTypeName(name) {
this._gqType.name = name;
this._gqcIsModified = true;
this.schemaComposer.add(this);
return this;
}
getDescription() {
return this._gqType.description || '';
}
setDescription(description) {
this._gqType.description = description;
this._gqcIsModified = true;
return this;
}
clone(newTypeNameOrTC) {
if (!newTypeNameOrTC) {
throw new Error('You should provide newTypeName:string for InterfaceTypeComposer.clone()');
}
const cloned = newTypeNameOrTC instanceof InterfaceTypeComposer
? newTypeNameOrTC
: InterfaceTypeComposer.create(newTypeNameOrTC, this.schemaComposer);
cloned._gqcFields = (0, misc_1.mapEachKey)(this._gqcFields, (fieldConfig) => (Object.assign(Object.assign({}, fieldConfig), { args: (0, misc_1.mapEachKey)(fieldConfig.args, (argConfig) => (Object.assign(Object.assign({}, argConfig), { extensions: Object.assign({}, argConfig.extensions), directives: [...(argConfig.directives || [])] }))), extensions: Object.assign({}, fieldConfig.extensions), directives: [...(fieldConfig.directives || [])] })));
cloned._gqcInterfaces = [...this._gqcInterfaces];
if (this._gqcTypeResolvers) {
cloned._gqcTypeResolvers = new Map(this._gqcTypeResolvers);
}
cloned._gqcFallbackResolveType = this._gqcFallbackResolveType;
cloned._gqcExtensions = Object.assign({}, this._gqcExtensions);
cloned.setDescription(this.getDescription());
cloned.setDirectives(this.getDirectives());
return cloned;
}
cloneTo(anotherSchemaComposer, cloneMap = new Map()) {
if (!anotherSchemaComposer) {
throw new Error('You should provide SchemaComposer for InterfaceTypeComposer.cloneTo()');
}
if (cloneMap.has(this))
return cloneMap.get(this);
const cloned = InterfaceTypeComposer.create(this.getTypeName(), anotherSchemaComposer);
cloneMap.set(this, cloned);
cloned._gqcFields = (0, misc_1.mapEachKey)(this._gqcFields, (fieldConfig) => (Object.assign(Object.assign({}, fieldConfig), { type: (0, typeHelpers_1.cloneTypeTo)(fieldConfig.type, anotherSchemaComposer, cloneMap), args: (0, misc_1.mapEachKey)(fieldConfig.args, (argConfig) => (Object.assign(Object.assign({}, argConfig), { type: (0, typeHelpers_1.cloneTypeTo)(argConfig.type, anotherSchemaComposer, cloneMap), extensions: Object.assign({}, argConfig.extensions), directives: [...(argConfig.directives || [])] }))), extensions: Object.assign({}, fieldConfig.extensions), directives: [...(fieldConfig.directives || [])] })));
cloned._gqcInterfaces = this._gqcInterfaces.map((i) => i.cloneTo(anotherSchemaComposer, cloneMap));
cloned._gqcExtensions = Object.assign({}, this._gqcExtensions);
cloned.setDescription(this.getDescription());
const typeResolversMap = this.getTypeResolvers();
if (typeResolversMap.size > 0) {
const clonedTypeResolvers = new Map();
typeResolversMap.forEach((fn, tc) => {
const clonedTC = (0, typeHelpers_1.cloneTypeTo)(tc, anotherSchemaComposer, cloneMap);
clonedTypeResolvers.set(clonedTC, fn);
});
cloned.setTypeResolvers(clonedTypeResolvers);
}
if (this._gqcFallbackResolveType) {
cloned._gqcFallbackResolveType = (0, typeHelpers_1.cloneTypeTo)(this._gqcFallbackResolveType, anotherSchemaComposer, cloneMap);
}
return cloned;
}
merge(type) {
let tc;
if (type instanceof ObjectTypeComposer_1.ObjectTypeComposer || type instanceof InterfaceTypeComposer) {
tc = type;
}
else if (type instanceof graphql_1.GraphQLObjectType) {
tc = ObjectTypeComposer_1.ObjectTypeComposer.createTemp(type, this.schemaComposer);
}
else if (type instanceof graphql_1.GraphQLInterfaceType) {
tc = InterfaceTypeComposer.createTemp(type, this.schemaComposer);
}
else {
throw new Error(`Cannot merge ${(0, misc_1.inspect)(type)} with InterfaceType(${this.getTypeName()}). Provided type should be GraphQLInterfaceType, GraphQLObjectType, InterfaceTypeComposer or ObjectTypeComposer.`);
}
const fields = Object.assign({}, tc.getFields());
Object.keys(fields).forEach((fieldName) => {
fields[fieldName] = Object.assign(Object.assign({}, fields[fieldName]), { args: Object.assign({}, fields[fieldName].args), type: tc.getFieldTypeName(fieldName) });
tc.getFieldArgNames(fieldName).forEach((argName) => {
fields[fieldName].args[argName] = Object.assign(Object.assign({}, fields[fieldName].args[argName]), { type: tc.getFieldArgTypeName(fieldName, argName) });
});
});
this.addFields(fields);
this.addInterfaces(tc.getInterfaces().map((i) => i.getTypeName()));
return this;
}
getInputType() {
return this.getInputTypeComposer().getType();
}
hasInputTypeComposer() {
return !!this._gqcInputTypeComposer;
}
setInputTypeComposer(itc) {
this._gqcInputTypeComposer = itc;
return this;
}
getInputTypeComposer(opts) {
if (!this._gqcInputTypeComposer) {
this._gqcInputTypeComposer = (0, toInputType_1.toInputObjectType)(this, opts);
}
return this._gqcInputTypeComposer;
}
getITC(opts) {
return this.getInputTypeComposer(opts);
}
removeInputTypeComposer() {
this._gqcInputTypeComposer = undefined;
return this;
}
getResolveType() {
return this._gqType.resolveType;
}
setResolveType(fn) {
this._gqType.resolveType = fn;
this._gqcIsModified = true;
return this;
}
hasTypeResolver(type) {
const typeResolversMap = this.getTypeResolvers();
return typeResolversMap.has(type);
}
getTypeResolvers() {
if (!this._gqcTypeResolvers) {
this._gqcTypeResolvers = new Map();
}
return this._gqcTypeResolvers;
}
getTypeResolverCheckFn(type) {
const typeResolversMap = this.getTypeResolvers();
if (!typeResolversMap.has(type)) {
throw new Error(`Type resolve function in interface '${this.getTypeName()}' is not defined for type ${(0, misc_1.inspect)(type)}.`);
}
return typeResolversMap.get(type);
}
getTypeResolverNames() {
const typeResolversMap = this.getTypeResolvers();
const names = [];
typeResolversMap.forEach((_, composeType) => {
if (composeType instanceof ObjectTypeComposer_1.ObjectTypeComposer) {
names.push(composeType.getTypeName());
}
else if (composeType && composeType.name) {
names.push(composeType.name);
}
});
return names;
}
getTypeResolverTypes() {
const typeResolversMap = this.getTypeResolvers();
const types = [];
typeResolversMap.forEach((_, composeType) => {
types.push((0, typeHelpers_1.getGraphQLType)(composeType));
});
return types;
}
setTypeResolvers(typeResolversMap) {
this._isTypeResolversValid(typeResolversMap);
this._gqcTypeResolvers = typeResolversMap;
this._initResolveTypeFn();
return this;
}
_initResolveTypeFn() {
const typeResolversMap = this._gqcTypeResolvers || new Map();
const fallbackType = this._gqcFallbackResolveType
? (0, typeHelpers_1.getGraphQLType)(this._gqcFallbackResolveType)
: null;
const fastEntries = [];
if (graphqlVersion_1.graphqlVersion >= 16) {
for (const [composeType, checkFn] of typeResolversMap.entries()) {
fastEntries.push([(0, typeHelpers_1.getComposeTypeName)(composeType, this.schemaComposer), checkFn]);
}
}
else {
for (const [composeType, checkFn] of typeResolversMap.entries()) {
fastEntries.push([(0, typeHelpers_1.getGraphQLType)(composeType), checkFn]);
}
}
let resolveType;
const isAsyncRuntime = this._isTypeResolversAsync(typeResolversMap);
if (isAsyncRuntime) {
resolveType = (value, context, info) => __awaiter(this, void 0, void 0, function* () {
for (const [_gqType, checkFn] of fastEntries) {
if (yield checkFn(value, context, info))
return _gqType;
}
return fallbackType;
});
}
else {
resolveType = (value, context, info) => {
for (const [_gqType, checkFn] of fastEntries) {
if (checkFn(value, context, info))
return _gqType;
}
return fallbackType;
};
}
this.setResolveType(resolveType);
return this;
}
_isTypeResolversValid(typeResolversMap) {
if (!(typeResolversMap instanceof Map)) {
throw new Error(`For interface ${this.getTypeName()} you should provide Map object for type resolvers.`);
}
for (const [composeType, checkFn] of typeResolversMap.entries()) {
this._isTypeResolverValid(composeType, checkFn);
}
return true;
}
_isTypeResolverValid(composeType, checkFn) {
try {
const type = (0, typeHelpers_1.getGraphQLType)(composeType);
if (!(type instanceof graphql_1.GraphQLObjectType))
throw new Error('Must be GraphQLObjectType');
}
catch (e) {
throw new Error(`For interface type resolver ${this.getTypeName()} you must provide GraphQLObjectType or ObjectTypeComposer, but provided ${(0, misc_1.inspect)(composeType)}`);
}
if (!(0, is_1.isFunction)(checkFn)) {
throw new Error(`Interface ${this.getTypeName()} has invalid check function for type ${(0, misc_1.inspect)(composeType)}`);
}
return true;
}
_isTypeResolversAsync(typeResolversMap) {
let res = false;
for (const [, checkFn] of typeResolversMap.entries()) {
try {
const r = checkFn({}, {}, {});
if (r instanceof Promise) {
r.catch(() => { });
res = true;
}
}
catch (e) {
}
}
return res;
}
addTypeResolver(type, checkFn) {
const typeResolversMap = this.getTypeResolvers();
this._isTypeResolverValid(type, checkFn);
typeResolversMap.set(type, checkFn);
this._initResolveTypeFn();
if (type instanceof ObjectTypeComposer_1.ObjectTypeComposer) {
type.addInterface(this);
}
this.schemaComposer.addSchemaMustHaveType(type);
return this;
}
removeTypeResolver(type) {
const typeResolversMap = this.getTypeResolvers();
typeResolversMap.delete(type);
this._initResolveTypeFn();
return this;
}
setTypeResolverFallback(type) {
if (type) {
if (type instanceof ObjectTypeComposer_1.ObjectTypeComposer) {
type.addInterface(this);
}
this.schemaComposer.addSchemaMustHaveType(type);
}
this._gqcFallbackResolveType = type;
this._initResolveTypeFn();
return this;
}
getInterfaces() {
return this._gqcInterfaces;
}
getInterfacesTypes() {
return this._gqcInterfaces.map((i) => i.getType());
}
setInterfaces(interfaces) {
this._gqcInterfaces = (0, configToDefine_1.convertInterfaceArrayAsThunk)(interfaces, this.schemaComposer);
this._gqcIsModified = true;
return this;
}
hasInterface(iface) {
const typeName = (0, typeHelpers_1.getComposeTypeName)(iface, this.schemaComposer);
return !!this._gqcInterfaces.find((i) => i.getTypeName() === typeName);
}
addInterface(iface) {
if (!this.hasInterface(iface)) {
this._gqcInterfaces.push(this.schemaComposer.typeMapper.convertInterfaceTypeDefinition(iface));
this._gqcIsModified = true;
}
return this;
}
addInterfaces(ifaces) {
if (!Array.isArray(ifaces)) {
throw new Error(`InterfaceTypeComposer[${this.getTypeName()}].addInterfaces() accepts only array`);
}
ifaces.forEach((iface) => this.addInterface(iface));
return this;
}
removeInterface(iface) {
const typeName = (0, typeHelpers_1.getComposeTypeName)(iface, this.schemaComposer);
this._gqcInterfaces = this._gqcInterfaces.filter((i) => i.getTypeName() !== typeName);
this._gqcIsModified = true;
return this;
}
getExtensions() {
if (!this._gqcExtensions) {
return {};
}
else {
return this._gqcExtensions;
}
}
setExtensions(extensions) {
this._gqcExtensions = extensions;
this._gqcIsModified = true;
return this;
}
extendExtensions(extensions) {
const current = this.getExtensions();
this.setExtensions(Object.assign(Object.assign({}, current), extensions));
return this;
}
clearExtensions() {
this.setExtensions({});
return this;
}
getExtension(extensionName) {
const extensions = this.getExtensions();
return extensions[extensionName];
}
hasExtension(extensionName) {
const extensions = this.getExtensions();
return extensionName in extensions;
}
setExtension(extensionName, value) {
this.extendExtensions({
[extensionName]: value,
});
return this;
}
removeExtension(extensionName) {
const extensions = Object.assign({}, this.getExtensions());
delete extensions[extensionName];
this.setExtensions(extensions);
return this;
}
getFieldExtensions(fieldName) {
const field = this.getField(fieldName);
return field.extensions || {};
}
setFieldExtensions(fieldName, extensions) {
const field = this.getField(fieldName);
this.setField(fieldName, Object.assign(Object.assign({}, field), { extensions }));
return this;
}
extendFieldExtensions(fieldName, extensions) {
const current = this.getFieldExtensions(fieldName);
this.setFieldExtensions(fieldName, Object.assign(Object.assign({}, current), extensions));
return this;
}
clearFieldExtensions(fieldName) {
this.setFieldExtensions(fieldName, {});
return this;
}
getFieldExtension(fieldName, extensionName) {
const extensions = this.getFieldExtensions(fieldName);
return extensions[extensionName];
}
hasFieldExtension(fieldName, extensionName) {
const extensions = this.getFieldExtensions(fieldName);
return extensionName in extensions;
}
setFieldExtension(fieldName, extensionName, value) {
this.extendFieldExtensions(fieldName, {
[extensionName]: value,
});
return this;
}
removeFieldExtension(fieldName, extensionName) {
const extensions = Object.assign({}, this.getFieldExtensions(fieldName));
delete extensions[extensionName];
this.setFieldExtensions(fieldName, extensions);
return this;
}
getFieldArgExtensions(fieldName, argName) {
const ac = this.getFieldArg(fieldName, argName);
return ac.extensions || {};
}
setFieldArgExtensions(fieldName, argName, extensions) {
const ac = this.getFieldArg(fieldName, argName);
this.setFieldArg(fieldName, argName, Object.assign(Object.assign({}, ac), { extensions }));
return this;
}
extendFieldArgExtensions(fieldName, argName, extensions) {
const current = this.getFieldArgExtensions(fieldName, argName);
this.setFieldArgExtensions(fieldName, argName, Object.assign(Object.assign({}, current), extensions));
return this;
}
clearFieldArgExtensions(fieldName, argName) {
this.setFieldArgExtensions(fieldName, argName, {});
return this;
}
getFieldArgExtension(fieldName, argName, extensionName) {
const extensions = this.getFieldArgExtensions(fieldName, argName);
return extensions[extensionName];
}
hasFieldArgExtension(fieldName, argName, extensionName) {
const extensions = this.getFieldArgExtensions(fieldName, argName);
return extensionName in extensions;
}
setFieldArgExtension(fieldName, argName, extensionName, value) {
this.extendFieldArgExtensions(fieldName, argName, {
[extensionName]: value,
});
return this;
}
removeFieldArgExtension(fieldName, argName, extensionName) {
const extensions = Object.assign({}, this.getFieldArgExtensions(fieldName, argName));
delete extensions[extensionName];
this.setFieldArgExtensions(fieldName, argName, extensions);
return this;
}
getDirectives() {
return this._gqcDirectives || [];
}
setDirectives(directives) {
this._gqcDirectives = directives;
this._gqcIsModified = true;
return this;
}
getDirectiveNames() {
return this.getDirectives().map((d) => d.name);
}
getDirectiveByName(directiveName) {
const directive = this.getDirectives().find((d) => d.name === directiveName);
if (!directive)
return undefined;
return directive.args;
}
setDirectiveByName(directiveName, args) {
const directives = this.getDirectives();
const idx = directives.findIndex((d) => d.name === directiveName);
if (idx >= 0) {
directives[idx].args = args;
}
else {
directives.push({ name: directiveName, args });
}
this.setDirectives(directives);
return this;
}
getDirectiveById(idx) {
const directive = this.getDirectives()[idx];
if (!directive)
return undefined;
return directive.args;
}
getFieldDirectives(fieldName) {
return this.getField(fieldName).directives || [];
}
setFieldDirectives(fieldName, directives) {
const fc = this.getField(fieldName);
fc.directives = directives;
this._gqcIsModified = true;
return this;
}
getFieldDirectiveNames(fieldName) {
return this.getFieldDirectives(fieldName).map((d) => d.name);
}
getFieldDirectiveByName(fieldName, directiveName) {
const directive = this.getFieldDirectives(fieldName).find((d) => d.name === directiveName);
if (!directive)
return undefined;
return directive.args;
}
setFieldDirectiveByName(fieldName, directiveName, args) {
const directives = this.getFieldDirectives(fieldName);
const idx = directives.findIndex((d) => d.name === directiveName);
if (idx >= 0) {
directives[idx].args = args;
}
else {
directives.push({ name: directiveName, args });
}
this.setFieldDirectives(fieldName, directives);
return this;
}
getFieldDirectiveById(fieldName, idx) {
const directive = this.getFieldDirectives(fieldName)[idx];
if (!directive)
return undefined;
return directive.args;
}
getFieldArgDirectives(fieldName, argName) {
return this.getFieldArg(fieldName, argName).directives || [];
}
setFieldArgDirectives(fieldName, argName, directives) {
const ac = this.getFieldArg(fieldName, argName);
ac.directives = directives;
this._gqcIsModified = true;
return this;
}
getFieldArgDirectiveNames(fieldName, argName) {
return this.getFieldArgDirectives(fieldName, argName).map((d) => d.name);
}
getFieldArgDirectiveByName(fieldName, argName, directiveName) {
const directive = this.getFieldArgDirectives(fieldName, argName).find((d) => d.name === directiveName);
if (!directive)
return undefined;
return directive.args;
}
setFieldArgDirectiveByName(fieldName, argName, directiveName, args) {
const directives = this.getFieldArgDirectives(fieldName, argName);
const idx = directives.findIndex((d) => d.name === directiveName);
if (idx >= 0) {
directives[idx].args = args;
}
else {
directives.push({ name: directiveName, args });
}
this.setFieldArgDirectives(fieldName, argName, directives);
return this;
}
getFieldArgDirectiveById(fieldName, argName, idx) {
const directive = this.getFieldArgDirectives(fieldName, argName)[idx];
if (!directive)
return undefined;
return directive.args;
}
get(path) {
return (0, typeByPath_1.typeByPath)(this, path);
}
getNestedTCs(opts = {}, passedTypes = new Set()) {
const exclude = Array.isArray(opts.exclude) ? opts.exclude : [];
this.getFieldNames().forEach((fieldName) => {
const tc = this.getFieldTC(fieldName);
if (!passedTypes.has(tc) && !exclude.includes(tc.getTypeName())) {
passedTypes.add(tc);
if (tc instanceof ObjectTypeComposer_1.ObjectTypeComposer || tc instanceof UnionTypeComposer_1.UnionTypeComposer) {
tc.getNestedTCs(opts, passedTypes);
}
}
this.getFieldArgNames(fieldName).forEach((argName) => {
const itc = this.getFieldArgTC(fieldName, argName);
if (!passedTypes.has(itc) && !exclude.includes(itc.getTypeName())) {
passedTypes.add(itc);
if (itc instanceof InputTypeComposer_1.InputTypeComposer) {
itc.getNestedTCs(opts, passedTypes);
}
}
});
this.getInterfaces().forEach((t) => {
const iftc = t instanceof ThunkComposer_1.ThunkComposer ? t.ofType : t;
if (!passedTypes.has(iftc) && !exclude.includes(iftc.getTypeName())) {
passedTypes.add(iftc);
iftc.getNestedTCs(opts, passedTypes);
}
});
});
return passedTypes;
}
toSDL(opts) {
const _a = opts || {}, { deep } = _a, innerOpts = __rest(_a, ["deep"]);
innerOpts.sortTypes = innerOpts.sortTypes || false;
const exclude = Array.isArray(innerOpts.exclude) ? innerOpts.exclude : [];
if (deep) {
let r = '';
r += (0, schemaPrinter_1.printInterface)(this.getType(), innerOpts);
const nestedTypes = Array.from(this.getNestedTCs({ exclude }));
const sortMethod = (0, schemaPrinterSortTypes_1.getSortMethodFromOption)(innerOpts.sortAll || innerOpts.sortTypes);
if (sortMethod) {
nestedTypes.sort(sortMethod);
}
nestedTypes.forEach((t) => {
if (t !== this && !exclude.includes(t.getTypeName())) {
const sdl = t.toSDL(innerOpts);
if (sdl)
r += `\n\n${sdl}`;
}
});
return r;
}
return (0, schemaPrinter_1.printInterface)(this.getType(), innerOpts);
}
}
exports.InterfaceTypeComposer = InterfaceTypeComposer;
//# sourceMappingURL=InterfaceTypeComposer.js.map