Files
30-seconds-of-code/node_modules/graphql-compose/lib/SchemaComposer.js
2019-08-20 15:52:05 +02:00

669 lines
20 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SchemaComposer = exports.BUILT_IN_DIRECTIVES = void 0;
var _deprecate = _interopRequireDefault(require("./utils/deprecate"));
var _TypeStorage = require("./TypeStorage");
var _TypeMapper = require("./TypeMapper");
var _ObjectTypeComposer = require("./ObjectTypeComposer");
var _InputTypeComposer = require("./InputTypeComposer");
var _ScalarTypeComposer = require("./ScalarTypeComposer");
var _EnumTypeComposer = require("./EnumTypeComposer");
var _InterfaceTypeComposer = require("./InterfaceTypeComposer");
var _UnionTypeComposer = require("./UnionTypeComposer");
var _Resolver = require("./Resolver");
var _is = require("./utils/is");
var _misc = require("./utils/misc");
var _typeHelpers = require("./utils/typeHelpers");
var _graphql = require("./graphql");
var _default = _interopRequireDefault(require("./directive/default"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const BUILT_IN_DIRECTIVES = [_graphql.GraphQLSkipDirective, _graphql.GraphQLIncludeDirective, _graphql.GraphQLDeprecatedDirective, _default.default];
exports.BUILT_IN_DIRECTIVES = BUILT_IN_DIRECTIVES;
class SchemaComposer extends _TypeStorage.TypeStorage {
constructor(schema) {
super();
_defineProperty(this, "_schemaMustHaveTypes", []);
_defineProperty(this, "_directives", BUILT_IN_DIRECTIVES);
this.typeMapper = new _TypeMapper.TypeMapper(this);
if (schema instanceof _graphql.GraphQLSchema) {
this.merge(schema);
} // alive proper Flow type casting in autosuggestions for class with Generics
/* :: return this; */
}
get Query() {
return this.getOrCreateOTC('Query');
}
/* @deprecated 7.0.0 */
rootQuery() {
(0, _deprecate.default)('Use schemaComposer.Query property instead');
return this.getOrCreateOTC('Query');
}
get Mutation() {
return this.getOrCreateOTC('Mutation');
}
/* @deprecated 7.0.0 */
rootMutation() {
(0, _deprecate.default)('Use schemaComposer.Mutation property instead');
return this.getOrCreateOTC('Mutation');
}
get Subscription() {
return this.getOrCreateOTC('Subscription');
}
/* @deprecated 7.0.0 */
rootSubscription() {
(0, _deprecate.default)('Use schemaComposer.Subscription property instead');
return this.getOrCreateOTC('Subscription');
}
buildSchema(extraConfig) {
const roots = {};
if (this.has('Query')) {
const tc = this.getOTC('Query');
this.removeEmptyTypes(tc, new Set());
roots.query = tc.getType();
}
if (this.has('Mutation')) {
const tc = this.getOTC('Mutation');
this.removeEmptyTypes(tc, new Set());
roots.mutation = tc.getType();
}
if (this.has('Subscription')) {
const tc = this.getOTC('Subscription');
this.removeEmptyTypes(tc, new Set());
roots.subscription = tc.getType();
}
if (!roots.query) {
throw new Error('Can not build schema. Must be initialized Query type. See https://github.com/graphql/graphql-js/issues/448');
}
if (Object.keys(roots).length === 0) {
throw new Error('Can not build schema. Must be initialized at least one ' + 'of the following types: Query, Mutation, Subscription.');
}
const types = [...this._schemaMustHaveTypes.map(t => (0, _typeHelpers.getGraphQLType)(t)), // additional types, eg. used in Interfaces
...(extraConfig && Array.isArray(extraConfig.types) ? [...extraConfig.types] : [])];
const directives = [...this._directives, ...(extraConfig && Array.isArray(extraConfig.directives) ? [...extraConfig.directives] : [])];
return new _graphql.GraphQLSchema(_objectSpread({}, roots, extraConfig, {
types,
directives
}));
}
addSchemaMustHaveType(type) {
this._schemaMustHaveTypes.push(type);
return this;
}
removeEmptyTypes(tc, passedTypes = new Set()) {
tc.getFieldNames().forEach(fieldName => {
const fieldType = tc.getFieldType(fieldName);
if (fieldType instanceof _graphql.GraphQLObjectType) {
const typeName = fieldType.name;
if (!passedTypes.has(typeName)) {
passedTypes.add(typeName);
const fieldTC = new _ObjectTypeComposer.ObjectTypeComposer(fieldType, this);
if (Object.keys(fieldTC.getFields()).length > 0) {
this.removeEmptyTypes(fieldTC, passedTypes);
} else {
// eslint-disable-next-line
console.log(`graphql-compose: Delete field '${tc.getTypeName()}.${fieldName}' ` + `with type '${fieldTC.getTypeName()}', cause it does not have fields.`);
tc.removeField(fieldName);
}
}
}
});
}
merge(schema) {
let query;
let mutation;
let subscription;
let typeMap;
let directives;
if (schema instanceof SchemaComposer) {
query = schema.Query;
mutation = schema.Mutation;
subscription = schema.Subscription;
typeMap = schema.types;
directives = schema.getDirectives();
} else if (schema instanceof _graphql.GraphQLSchema) {
query = schema.getQueryType();
mutation = schema.getMutationType();
subscription = schema.getSubscriptionType();
typeMap = new Map();
(0, _misc.forEachKey)(schema.getTypeMap(), (v, k) => {
typeMap.set(k, v);
});
directives = schema.getDirectives();
} else {
throw new Error('SchemaComposer.merge() accepts only GraphQLSchema or SchemaComposer instances.');
} // Root types may have any name, so import them manually.
if (query) this.Query.merge(query);
if (mutation) this.Mutation.merge(mutation);
if (subscription) this.Subscription.merge(subscription); // Merging non-root types
typeMap.forEach((type, key) => {
// skip internal and root types
if (typeof key === 'string' && key.startsWith('__') || type === query || type === mutation || type === subscription) return; // merge regular types
if (this.has(key)) {
this.getAnyTC(key).merge(type);
} else {
this.set(key, type);
}
});
directives.forEach(directive => {
this.addDirective(directive);
});
return this;
}
/**
* -----------------------------------------------
* Like graphql-tools methods
* -----------------------------------------------
*/
addTypeDefs(typeDefs) {
const types = this.typeMapper.parseTypesFromString(typeDefs);
types.forEach(type => {
const name = type.getTypeName();
if (name !== 'Query' && name !== 'Mutation' && name !== 'Subscription') {
this.add(type);
}
});
if (types.has('Query')) {
const tc = types.get('Query');
if (!(tc instanceof _ObjectTypeComposer.ObjectTypeComposer)) {
throw new Error(`Type Query in typedefs isn't an Object Type.`);
}
this.Query.addFields(tc.getFields());
}
if (types.has('Mutation')) {
const tc = types.get('Mutation');
if (!(tc instanceof _ObjectTypeComposer.ObjectTypeComposer)) {
throw new Error(`Type Mutation in typedefs isn't an Object Type.`);
}
this.Mutation.addFields(tc.getFields());
}
if (types.has('Subscription')) {
const tc = types.get('Subscription');
if (!(tc instanceof _ObjectTypeComposer.ObjectTypeComposer)) {
throw new Error(`Type Subscription in typedefs isn't an Object Type.`);
}
this.Subscription.addFields(tc.getFields());
}
return types;
}
addResolveMethods(typesFieldsResolve) {
const typeNames = Object.keys(typesFieldsResolve);
typeNames.forEach(typeName => {
let type = this.get(typeName);
if (type instanceof _ScalarTypeComposer.ScalarTypeComposer) {
type = type.getType();
}
if (type instanceof _graphql.GraphQLScalarType) {
const maybeScalar = typesFieldsResolve[typeName];
if (maybeScalar instanceof _graphql.GraphQLScalarType) {
this.set(typeName, maybeScalar);
return;
}
if (typeof maybeScalar.name === 'string' && typeof maybeScalar.serialize === 'function') {
this.set(typeName, new _graphql.GraphQLScalarType(maybeScalar));
return;
}
}
const tc = this.getOTC(typeName);
const fieldsResolve = typesFieldsResolve[typeName];
const fieldNames = Object.keys(fieldsResolve);
fieldNames.forEach(fieldName => {
tc.extendField(fieldName, {
resolve: fieldsResolve[fieldName]
});
});
});
}
/**
* -----------------------------------------------
* Type methods
* -----------------------------------------------
*/
createObjectTC(typeDef) {
return _ObjectTypeComposer.ObjectTypeComposer.create(typeDef, this);
}
createInputTC(typeDef) {
return _InputTypeComposer.InputTypeComposer.create(typeDef, this);
}
createEnumTC(typeDef) {
return _EnumTypeComposer.EnumTypeComposer.create(typeDef, this);
}
createInterfaceTC(typeDef) {
return _InterfaceTypeComposer.InterfaceTypeComposer.create(typeDef, this);
}
createUnionTC(typeDef) {
return _UnionTypeComposer.UnionTypeComposer.create(typeDef, this);
}
createScalarTC(typeDef) {
return _ScalarTypeComposer.ScalarTypeComposer.create(typeDef, this);
}
createResolver(opts) {
return new _Resolver.Resolver(opts, this);
}
createTC(typeOrSDL) {
if (this.has(typeOrSDL)) {
return this.get(typeOrSDL);
}
const tc = this.createTempTC(typeOrSDL);
this.set(tc.getTypeName(), tc);
this.set(typeOrSDL, tc);
return tc;
}
createTempTC(typeOrSDL) {
let type;
if (typeof typeOrSDL === 'string') {
type = this.typeMapper.createType(typeOrSDL);
} else {
type = typeOrSDL;
}
if (type instanceof _ObjectTypeComposer.ObjectTypeComposer || type instanceof _InputTypeComposer.InputTypeComposer || type instanceof _ScalarTypeComposer.ScalarTypeComposer || type instanceof _EnumTypeComposer.EnumTypeComposer || type instanceof _InterfaceTypeComposer.InterfaceTypeComposer || type instanceof _UnionTypeComposer.UnionTypeComposer) {
return type;
} else if (type instanceof _graphql.GraphQLObjectType) {
return _ObjectTypeComposer.ObjectTypeComposer.createTemp(type, this);
} else if (type instanceof _graphql.GraphQLInputObjectType) {
return _InputTypeComposer.InputTypeComposer.createTemp(type, this);
} else if (type instanceof _graphql.GraphQLScalarType) {
return _ScalarTypeComposer.ScalarTypeComposer.createTemp(type, this);
} else if (type instanceof _graphql.GraphQLEnumType) {
return _EnumTypeComposer.EnumTypeComposer.createTemp(type, this);
} else if (type instanceof _graphql.GraphQLInterfaceType) {
return _InterfaceTypeComposer.InterfaceTypeComposer.createTemp(type, this);
} else if (type instanceof _graphql.GraphQLUnionType) {
return _UnionTypeComposer.UnionTypeComposer.createTemp(type, this);
}
throw new Error(`Cannot create as TypeComposer the following value: ${(0, _misc.inspect)(type)}.`);
}
/* @deprecated 7.0.0 */
getOrCreateTC(typeName, onCreate) {
(0, _deprecate.default)(`Use SchemaComposer.getOrCreateOTC() method instead`);
return this.getOrCreateOTC(typeName, onCreate);
}
getOrCreateOTC(typeName, onCreate) {
try {
return this.getOTC(typeName);
} catch (e) {
const tc = _ObjectTypeComposer.ObjectTypeComposer.create(typeName, this);
this.set(typeName, tc);
if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(tc);
return tc;
}
}
getOrCreateITC(typeName, onCreate) {
try {
return this.getITC(typeName);
} catch (e) {
const itc = _InputTypeComposer.InputTypeComposer.create(typeName, this);
this.set(typeName, itc);
if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(itc);
return itc;
}
}
getOrCreateETC(typeName, onCreate) {
try {
return this.getETC(typeName);
} catch (e) {
const etc = _EnumTypeComposer.EnumTypeComposer.create(typeName, this);
this.set(typeName, etc);
if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(etc);
return etc;
}
}
getOrCreateIFTC(typeName, onCreate) {
try {
return this.getIFTC(typeName);
} catch (e) {
const iftc = _InterfaceTypeComposer.InterfaceTypeComposer.create(typeName, this);
this.set(typeName, iftc);
if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(iftc);
return iftc;
}
}
getOrCreateUTC(typeName, onCreate) {
try {
return this.getUTC(typeName);
} catch (e) {
const utc = _UnionTypeComposer.UnionTypeComposer.create(typeName, this);
this.set(typeName, utc);
if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(utc);
return utc;
}
}
getOrCreateSTC(typeName, onCreate) {
try {
return this.getSTC(typeName);
} catch (e) {
const stc = _ScalarTypeComposer.ScalarTypeComposer.create(typeName, this);
this.set(typeName, stc);
if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(stc);
return stc;
}
}
/* @deprecated 7.0.0 */
getTC(typeName) {
(0, _deprecate.default)(`Use SchemaComposer.getOTC() method instead`);
return this.getOTC(typeName);
}
getOTC(typeName) {
if (this.hasInstance(typeName, _graphql.GraphQLObjectType)) {
return _ObjectTypeComposer.ObjectTypeComposer.create(this.get(typeName), this);
}
if (this.hasInstance(typeName, _ObjectTypeComposer.ObjectTypeComposer)) {
return this.get(typeName);
}
throw new Error(`Cannot find ObjectTypeComposer with name ${typeName}`);
}
getITC(typeName) {
if (this.hasInstance(typeName, _graphql.GraphQLInputObjectType)) {
return _InputTypeComposer.InputTypeComposer.create(this.get(typeName), this);
}
if (this.hasInstance(typeName, _InputTypeComposer.InputTypeComposer)) {
return this.get(typeName);
}
throw new Error(`Cannot find InputTypeComposer with name ${typeName}`);
}
getETC(typeName) {
if (this.hasInstance(typeName, _graphql.GraphQLEnumType)) {
return _EnumTypeComposer.EnumTypeComposer.create(this.get(typeName), this);
}
if (this.hasInstance(typeName, _EnumTypeComposer.EnumTypeComposer)) {
return this.get(typeName);
}
throw new Error(`Cannot find EnumTypeComposer with name ${typeName}`);
}
getIFTC(typeName) {
if (this.hasInstance(typeName, _graphql.GraphQLInterfaceType)) {
return _InterfaceTypeComposer.InterfaceTypeComposer.create(this.get(typeName), this);
}
if (this.hasInstance(typeName, _InterfaceTypeComposer.InterfaceTypeComposer)) {
return this.get(typeName);
}
throw new Error(`Cannot find InterfaceTypeComposer with name ${typeName}`);
}
getUTC(typeName) {
if (this.hasInstance(typeName, _graphql.GraphQLUnionType)) {
return _UnionTypeComposer.UnionTypeComposer.create(this.get(typeName), this);
}
if (this.hasInstance(typeName, _UnionTypeComposer.UnionTypeComposer)) {
return this.get(typeName);
}
throw new Error(`Cannot find UnionTypeComposer with name ${typeName}`);
}
getSTC(typeName) {
if (this.hasInstance(typeName, _graphql.GraphQLScalarType)) {
return _ScalarTypeComposer.ScalarTypeComposer.create(this.get(typeName), this);
}
if (this.hasInstance(typeName, _ScalarTypeComposer.ScalarTypeComposer)) {
return this.get(typeName);
}
throw new Error(`Cannot find ScalarTypeComposer with name ${typeName}`);
}
getAnyTC(typeOrName) {
let type;
if (typeof typeOrName === 'string') {
type = this.get(typeOrName);
} else {
type = typeOrName;
}
if (type == null) {
throw new Error(`Cannot find type with name ${typeOrName}`);
} else if (type instanceof _ObjectTypeComposer.ObjectTypeComposer || type instanceof _InputTypeComposer.InputTypeComposer || type instanceof _ScalarTypeComposer.ScalarTypeComposer || type instanceof _EnumTypeComposer.EnumTypeComposer || type instanceof _InterfaceTypeComposer.InterfaceTypeComposer || type instanceof _UnionTypeComposer.UnionTypeComposer) {
return type;
}
while (type instanceof _graphql.GraphQLList || type instanceof _graphql.GraphQLNonNull) {
type = type.ofType;
}
if (type instanceof _graphql.GraphQLObjectType) {
return _ObjectTypeComposer.ObjectTypeComposer.create(type, this);
} else if (type instanceof _graphql.GraphQLInputObjectType) {
return _InputTypeComposer.InputTypeComposer.create(type, this);
} else if (type instanceof _graphql.GraphQLScalarType) {
return _ScalarTypeComposer.ScalarTypeComposer.create(type, this);
} else if (type instanceof _graphql.GraphQLEnumType) {
return _EnumTypeComposer.EnumTypeComposer.create(type, this);
} else if (type instanceof _graphql.GraphQLInterfaceType) {
return _InterfaceTypeComposer.InterfaceTypeComposer.create(type, this);
} else if (type instanceof _graphql.GraphQLUnionType) {
return _UnionTypeComposer.UnionTypeComposer.create(type, this);
}
throw new Error(`Type with name ${(0, _misc.inspect)(typeOrName)} cannot be obtained as any Composer helper. Put something strange?`);
}
addAsComposer(typeOrSDL) {
const composer = this.createTempTC(typeOrSDL);
this.set(composer.getTypeName(), composer);
return composer.getTypeName();
}
/**
* -----------------------------------------------
* Storage methods
* -----------------------------------------------
*/
clear() {
super.clear();
this._schemaMustHaveTypes = [];
this._directives = BUILT_IN_DIRECTIVES;
this.typeMapper.initScalars();
}
add(typeOrSDL) {
if (typeof typeOrSDL === 'string') {
return this.addAsComposer(typeOrSDL);
} else {
return super.add(typeOrSDL);
}
}
/**
* -----------------------------------------------
* Directive methods
* -----------------------------------------------
*/
addDirective(directive) {
if (!(directive instanceof _graphql.GraphQLDirective)) {
throw new Error(`You should provide GraphQLDirective to schemaComposer.addDirective(), but recieved ${(0, _misc.inspect)(directive)}`);
}
if (!this.hasDirective(directive)) {
this._directives.push(directive);
}
return this;
}
removeDirective(directive) {
this._directives = this._directives.filter(o => o !== directive);
return this;
}
getDirectives() {
return this._directives;
}
/**
* This method used in TypeMapper and for fast parsing
*/
_getDirective(name) {
const directives = this.getDirectives();
return directives.find(d => d.name === name);
}
getDirective(name) {
const directive = this._getDirective(name);
if (!directive) {
throw new Error(`Directive instance with name ${name} does not exists.`);
}
return directive;
}
hasDirective(directive) {
if (!directive) return false;
if (typeof directive === 'string') {
const name = directive.startsWith('@') ? directive.slice(1) : directive;
return !!this._directives.find(o => o.name === name);
} else if (directive instanceof _graphql.GraphQLDirective) {
return !!this._directives.find(o => o === directive);
}
return false;
}
/**
* -----------------------------------------------
* Misc methods
* -----------------------------------------------
*/
// disable redundant noise in console.logs
toString() {
return 'SchemaComposer';
}
toJSON() {
return 'SchemaComposer';
}
inspect() {
return 'SchemaComposer';
}
}
exports.SchemaComposer = SchemaComposer;