graphql-compose
Version:
GraphQL schema builder from different data sources with middleware extensions.
432 lines • 17 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnumTypeComposer = void 0;
const graphql_1 = require("./graphql");
const is_1 = require("./utils/is");
const misc_1 = require("./utils/misc");
const configToDefine_1 = require("./utils/configToDefine");
const graphqlVersion_1 = require("./utils/graphqlVersion");
const SchemaComposer_1 = require("./SchemaComposer");
const ListComposer_1 = require("./ListComposer");
const NonNullComposer_1 = require("./NonNullComposer");
const typeHelpers_1 = require("./utils/typeHelpers");
const schemaPrinter_1 = require("./utils/schemaPrinter");
const definitionNode_1 = require("./utils/definitionNode");
class EnumTypeComposer {
constructor(graphqlType, schemaComposer) {
if (!(schemaComposer instanceof SchemaComposer_1.SchemaComposer)) {
throw new Error('You must provide SchemaComposer instance as a second argument for `new EnumTypeComposer(GraphQLEnumType, SchemaComposer)`');
}
if (!(graphqlType instanceof graphql_1.GraphQLEnumType)) {
throw new Error('EnumTypeComposer accept only GraphQLEnumType in constructor');
}
this.schemaComposer = schemaComposer;
this._gqType = graphqlType;
this.schemaComposer.set(graphqlType, this);
this.schemaComposer.set(graphqlType.name, this);
this._gqcFields = (0, configToDefine_1.convertEnumValuesToConfig)(this._gqType.getValues(), this.schemaComposer);
if (!this._gqType.astNode) {
this._gqType.astNode = (0, definitionNode_1.getEnumTypeDefinitionNode)(this);
}
this._gqcIsModified = false;
}
static create(typeDef, schemaComposer) {
if (!(schemaComposer instanceof SchemaComposer_1.SchemaComposer)) {
throw new Error('You must provide SchemaComposer instance as a second argument for `EnumTypeComposer.create(typeDef, schemaComposer)`');
}
if (schemaComposer.hasInstance(typeDef, EnumTypeComposer)) {
return schemaComposer.getETC(typeDef);
}
const etc = this.createTemp(typeDef, schemaComposer);
if (schemaComposer)
schemaComposer.add(etc);
return etc;
}
static createTemp(typeDef, schemaComposer) {
const sc = schemaComposer || new SchemaComposer_1.SchemaComposer();
let ETC;
if ((0, is_1.isString)(typeDef)) {
const typeName = typeDef;
if ((0, typeHelpers_1.isTypeNameString)(typeName)) {
ETC = new EnumTypeComposer(new graphql_1.GraphQLEnumType({
name: typeName,
values: graphqlVersion_1.graphqlVersion < 13 ? { _OldGraphqlStubValue_: {} } : {},
}), sc);
}
else {
ETC = sc.typeMapper.convertSDLTypeDefinition(typeName);
if (!(ETC instanceof EnumTypeComposer)) {
throw new Error('You should provide correct GraphQLEnumType type definition. ' +
'Eg. `enum MyType { KEY1 KEY2 KEY3 }`');
}
}
}
else if (typeDef instanceof graphql_1.GraphQLEnumType) {
ETC = new EnumTypeComposer(typeDef, sc);
}
else if ((0, is_1.isObject)(typeDef)) {
const type = new graphql_1.GraphQLEnumType(Object.assign({}, typeDef));
ETC = new EnumTypeComposer(type, sc);
ETC.setFields(typeDef.values || {});
ETC.setExtensions(typeDef.extensions);
if (Array.isArray(typeDef === null || typeDef === void 0 ? void 0 : typeDef.directives)) {
ETC.setDirectives(typeDef.directives);
}
}
else {
throw new Error(`You should provide GraphQLEnumTypeConfig or string with enum name or SDL. Provided:\n${(0, misc_1.inspect)(typeDef)}`);
}
return ETC;
}
hasField(name) {
const values = this.getFields();
return !!values[name];
}
getFields() {
return this._gqcFields;
}
getField(name) {
const values = this.getFields();
if (!values[name]) {
throw new Error(`Cannot get value '${name}' from enum type '${this.getTypeName()}'. Value with such name does not exist.`);
}
return values[name];
}
getFieldNames() {
return Object.keys(this._gqcFields);
}
setFields(values) {
this._gqcFields = {};
Object.keys(values).forEach((valueName) => {
this.setField(valueName, values[valueName]);
});
return this;
}
setField(name, valueConfig) {
this._gqcFields[name] = {
value: valueConfig.hasOwnProperty('value') ? valueConfig.value : name,
description: valueConfig.description,
deprecationReason: valueConfig.deprecationReason,
extensions: valueConfig.extensions || {},
directives: valueConfig.directives || [],
};
this._gqcIsModified = true;
return this;
}
addFields(newValues) {
Object.keys(newValues).forEach((valueName) => {
this.setField(valueName, newValues[valueName]);
});
return this;
}
removeField(nameOrArray) {
const valueNames = Array.isArray(nameOrArray) ? nameOrArray : [nameOrArray];
valueNames.forEach((valueName) => {
delete this._gqcFields[valueName];
this._gqcIsModified = true;
});
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(name, partialValueConfig) {
let prevValueConfig;
try {
prevValueConfig = this.getField(name);
}
catch (e) {
throw new Error(`Cannot extend value '${name}' from enum '${this.getTypeName()}'. Value does not exist.`);
}
this.setField(name, Object.assign(Object.assign(Object.assign({}, prevValueConfig), partialValueConfig), { extensions: Object.assign(Object.assign({}, (prevValueConfig.extensions || {})), (partialValueConfig.extensions || {})), directives: [...(prevValueConfig.directives || []), ...(partialValueConfig.directives || [])] }));
return this;
}
deprecateFields(fields) {
const existedFieldNames = this.getFieldNames();
if (typeof fields === 'string') {
if (existedFieldNames.indexOf(fields) === -1) {
throw new Error(`Cannot deprecate non-existent value '${fields}' from enum '${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 value '${field}' from enum '${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 value '${field}' from enum '${this.getTypeName()}'`);
}
const deprecationReason = fieldMap[field];
this.extendField(field, { deprecationReason });
});
}
return this;
}
getType() {
const gqType = this._gqType;
if (this._gqcIsModified) {
this._gqcIsModified = false;
gqType.astNode = (0, definitionNode_1.getEnumTypeDefinitionNode)(this);
if (graphqlVersion_1.graphqlVersion >= 14) {
gqType._values = (0, configToDefine_1.defineEnumValues)(gqType, this._gqcFields, gqType.astNode);
gqType._valueLookup = new Map(gqType._values.map((enumValue) => [enumValue.value, enumValue]));
gqType._nameLookup = (0, misc_1.keyMap)(gqType._values, (value) => value.name);
}
else {
delete gqType._valueLookup;
delete gqType._nameLookup;
gqType._values = (0, configToDefine_1.defineEnumValues)(gqType, this._gqcFields, gqType.astNode);
}
}
return 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 EnumTypeComposer.clone()');
}
const cloned = newTypeNameOrTC instanceof EnumTypeComposer
? newTypeNameOrTC
: EnumTypeComposer.create(newTypeNameOrTC, this.schemaComposer);
cloned._gqcFields = (0, misc_1.mapEachKey)(this._gqcFields, (fieldConfig) => (Object.assign(Object.assign({}, fieldConfig), { extensions: Object.assign({}, fieldConfig.extensions), directives: fieldConfig.directives && [...(fieldConfig.directives || [])] })));
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 EnumTypeComposer.cloneTo()');
}
if (cloneMap.has(this))
return cloneMap.get(this);
const cloned = EnumTypeComposer.create(this.getTypeName(), anotherSchemaComposer);
cloneMap.set(this, cloned);
return this.clone(cloned);
}
merge(type) {
let tc;
if (type instanceof graphql_1.GraphQLEnumType) {
tc = EnumTypeComposer.createTemp(type, this.schemaComposer);
}
else if (type instanceof EnumTypeComposer) {
tc = type;
}
else {
throw new Error(`Cannot merge ${(0, misc_1.inspect)(type)} with EnumType(${this.getTypeName()}). Provided type should be GraphQLEnumType or EnumTypeComposer.`);
}
this.addFields(tc.getFields());
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;
}
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;
}
toSDL(opts) {
return (0, schemaPrinter_1.printEnum)(this.getType(), opts);
}
}
exports.EnumTypeComposer = EnumTypeComposer;
//# sourceMappingURL=EnumTypeComposer.js.map