Socket
Socket
Sign inDemoInstall

@graphql-tools/schema

Package Overview
Dependencies
Maintainers
3
Versions
1118
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.1-alpha-ecad9d5.0 to 5.0.1-alpha-f4c5dfe.0

2

addCatchUndefinedToSchema.d.ts
import { GraphQLSchema } from 'graphql';
export declare function addCatchUndefinedToSchema(schema: GraphQLSchema): void;
export declare function addCatchUndefinedToSchema(schema: GraphQLSchema): GraphQLSchema;
import { GraphQLSchema } from 'graphql';
import { ILogger } from './types';
export declare function addErrorLoggingToSchema(schema: GraphQLSchema, logger?: ILogger): void;
export declare function addErrorLoggingToSchema(schema: GraphQLSchema, logger?: ILogger): GraphQLSchema;
import { GraphQLSchema, GraphQLFieldResolver } from 'graphql';
export declare function addSchemaLevelResolver(schema: GraphQLSchema, fn: GraphQLFieldResolver<any, any>): void;
export declare function addSchemaLevelResolver(schema: GraphQLSchema, fn: GraphQLFieldResolver<any, any>): GraphQLSchema;
import { GraphQLSchema } from 'graphql';
import { IDirectiveResolvers } from '@graphql-tools/utils';
export declare function attachDirectiveResolvers(schema: GraphQLSchema, directiveResolvers: IDirectiveResolvers): void;
export declare function attachDirectiveResolvers(schema: GraphQLSchema, directiveResolvers: IDirectiveResolvers): GraphQLSchema;
import { GraphQLSchema } from 'graphql';
import { IResolvers } from '@graphql-tools/utils';
export declare function extendResolversFromInterfaces(schema: GraphQLSchema, resolvers: IResolvers): Record<string, import("graphql").GraphQLScalarType | (() => any) | Record<string, string | number> | import("../../utils/src").IResolverObject<any, any, any> | import("../../utils/src").IResolverOptions<any, any, any>>;
export declare function extendResolversFromInterfaces(schema: GraphQLSchema, resolvers: IResolvers): IResolvers;

@@ -12,20 +12,21 @@ 'use strict';

// TODO test that schema is a schema, fn is a function
const rootTypes = [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()].filter(x => Boolean(x));
rootTypes.forEach(type => {
if (type != null) {
const fnToRunOnlyOnce = runAtMostOncePerRequest(fn);
return utils.mapSchema(schema, {
[utils.MapperKind.ROOT_FIELD]: (fieldConfig, _fieldName, typeName, schema) => {
// XXX this should run at most once per request to simulate a true root resolver
// for graphql-js this is an approximation that works with queries but not mutations
const rootResolveFn = runAtMostOncePerRequest(fn);
const fields = type.getFields();
Object.keys(fields).forEach(fieldName => {
// XXX if the type is a subscription, a same query AST will be ran multiple times so we
// deactivate here the runOnce if it's a subscription. This may not be optimal though...
if (type === schema.getSubscriptionType()) {
fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, fn);
}
else {
fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, rootResolveFn);
}
});
}
// XXX if the type is a subscription, a same query AST will be ran multiple times so we
// deactivate here the runOnce if it's a subscription. This may not be optimal though...
const subscription = schema.getSubscriptionType();
if (subscription != null && subscription.name === typeName) {
return {
...fieldConfig,
resolve: wrapResolver(fieldConfig.resolve, fn),
};
}
return {
...fieldConfig,
resolve: wrapResolver(fieldConfig.resolve, fnToRunOnlyOnce),
};
},
});

@@ -121,23 +122,25 @@ }

}
const schemaDirectives = Object.create(null);
Object.keys(directiveResolvers).forEach(directiveName => {
schemaDirectives[directiveName] = class extends utils.SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const resolver = directiveResolvers[directiveName];
const originalResolver = field.resolve != null ? field.resolve : graphql.defaultFieldResolver;
const directiveArgs = this.args;
field.resolve = (...args) => {
const [source /* original args */, , context, info] = args;
return resolver(() => new Promise((resolve, reject) => {
const result = originalResolver.apply(field, args);
if (result instanceof Error) {
reject(result);
}
resolve(result);
}), source, directiveArgs, context, info);
};
}
};
return utils.mapSchema(schema, {
[utils.MapperKind.OBJECT_FIELD]: fieldConfig => {
const newFieldConfig = { ...fieldConfig };
const directives = utils.getDirectives(schema, fieldConfig);
Object.keys(directives).forEach(directiveName => {
if (directiveResolvers[directiveName]) {
const resolver = directiveResolvers[directiveName];
const originalResolver = newFieldConfig.resolve != null ? newFieldConfig.resolve : graphql.defaultFieldResolver;
const directiveArgs = directives[directiveName];
newFieldConfig.resolve = (source, originalArgs, context, info) => {
return resolver(() => new Promise((resolve, reject) => {
const result = originalResolver(source, originalArgs, context, info);
if (result instanceof Error) {
reject(result);
}
resolve(result);
}), source, directiveArgs, context, info);
};
}
});
return newFieldConfig;
},
});
utils.SchemaDirectiveVisitor.visitSchemaDirectives(schema, schemaDirectives);
}

@@ -305,10 +308,27 @@

typeNames.forEach(typeName => {
const typeResolvers = resolvers[typeName];
const type = schema.getType(typeName);
if ('getInterfaces' in type) {
const interfaceResolvers = type.getInterfaces().map(iFace => resolvers[iFace.name]);
extendedResolvers[typeName] = Object.assign({}, ...interfaceResolvers, typeResolvers);
const allInterfaceResolvers = type
.getInterfaces()
.map(iFace => resolvers[iFace.name])
.filter(interfaceResolvers => interfaceResolvers != null);
extendedResolvers[typeName] = {};
allInterfaceResolvers.forEach(interfaceResolvers => {
Object.keys(interfaceResolvers).forEach(fieldName => {
if (fieldName === '__isTypeOf' || !fieldName.startsWith('__')) {
extendedResolvers[typeName][fieldName] = interfaceResolvers[fieldName];
}
});
});
const typeResolvers = resolvers[typeName];
extendedResolvers[typeName] = {
...extendedResolvers[typeName],
...typeResolvers,
};
}
else if (typeResolvers != null) {
extendedResolvers[typeName] = typeResolvers;
else {
const typeResolvers = resolvers[typeName];
if (typeResolvers != null) {
extendedResolvers[typeName] = typeResolvers;
}
}

@@ -327,3 +347,3 @@ });

: schemaOrOptions;
const { schema, resolvers: inputResolvers, defaultFieldResolver, resolverValidationOptions = {}, inheritResolversFromInterfaces = false, } = options;
let { schema, resolvers: inputResolvers, defaultFieldResolver, resolverValidationOptions = {}, inheritResolversFromInterfaces = false, } = options;
const { allowResolversNotInSchema = false, requireResolversForResolveType } = resolverValidationOptions;

@@ -333,110 +353,161 @@ const resolvers = inheritResolversFromInterfaces

: inputResolvers;
const typeMap = schema.getTypeMap();
Object.keys(resolvers).forEach(typeName => {
const resolverValue = resolvers[typeName];
const resolverType = typeof resolverValue;
if (resolverType !== 'object' && resolverType !== 'function') {
throw new Error(`"${typeName}" defined in resolvers, but has invalid value "${resolverValue}". A resolver's value must be of type object or function.`);
if (typeName === '__schema') {
if (resolverType !== 'function') {
throw new Error(`"${typeName}" defined in resolvers, but has invalid value "${resolverValue}". A schema resolver's value must be of type object or function.`);
}
}
const type = schema.getType(typeName);
if (!type && typeName !== '__schema') {
if (allowResolversNotInSchema) {
return;
else {
if (resolverType !== 'object') {
throw new Error(`"${typeName}" defined in resolvers, but has invalid value "${resolverValue}". The resolver's value must be of type object.`);
}
throw new Error(`"${typeName}" defined in resolvers, but not in schema`);
}
if (graphql.isScalarType(type)) {
// Support -- without recommending -- overriding default scalar types
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
type[fieldName.substring(2)] = resolverValue[fieldName];
const type = schema.getType(typeName);
if (type == null) {
if (allowResolversNotInSchema) {
return;
}
else {
type[fieldName] = resolverValue[fieldName];
}
});
throw new Error(`"${typeName}" defined in resolvers, but not in schema`);
}
else if (graphql.isSpecifiedScalarType(type)) {
// allow -- without recommending -- overriding of specified scalar types
const resolverValue = resolvers[typeName];
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
type[fieldName.substring(2)] = resolverValue[fieldName];
}
else {
type[fieldName] = resolverValue[fieldName];
}
});
}
}
else if (graphql.isEnumType(type)) {
// We've encountered an enum resolver that is being used to provide an
// internal enum value.
// Reference: https://www.apollographql.com/docs/graphql-tools/scalars.html#internal-values
Object.keys(resolverValue).forEach(fieldName => {
if (!type.getValue(fieldName)) {
if (allowResolversNotInSchema) {
});
schema = utils.mapSchema(schema, {
[utils.MapperKind.SCALAR_TYPE]: type => {
const config = type.toConfig();
const resolverValue = resolvers[type.name];
if (!graphql.isSpecifiedScalarType(type) && resolverValue != null) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
}
else {
config[fieldName] = resolverValue[fieldName];
}
});
return new graphql.GraphQLScalarType(config);
}
},
[utils.MapperKind.ENUM_TYPE]: type => {
const resolverValue = resolvers[type.name];
const config = type.toConfig();
const enumValueConfigMap = config.values;
if (resolverValue != null) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
}
else if (!enumValueConfigMap[fieldName]) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${type.name}.${fieldName} was defined in resolvers, but not present within ${type.name}`);
}
else {
enumValueConfigMap[fieldName].value = resolverValue[fieldName];
}
});
return new graphql.GraphQLEnumType(config);
}
},
[utils.MapperKind.UNION_TYPE]: type => {
const resolverValue = resolvers[type.name];
if (resolverValue != null) {
const config = type.toConfig();
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
// this is for isTypeOf and resolveType and all the other stuff.
config[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
throw new Error(`${typeName}.${fieldName} was defined in resolvers, but enum is not in schema`);
}
});
const config = type.toConfig();
const values = type.getValues();
const newValues = values.reduce((prev, value) => ({
...prev,
[value.name]: {
value: Object.keys(resolverValue).includes(value.name) ? resolverValue[value.name] : value.name,
deprecationReason: value.deprecationReason,
description: value.description,
astNode: value.astNode,
},
}), {});
// healSchema called later to update all fields to new type
typeMap[typeName] = new graphql.GraphQLEnumType({
...config,
values: newValues,
});
}
else if (graphql.isUnionType(type)) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
// this is for isTypeOf and resolveType and all the other stuff.
type[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${typeName} was defined in resolvers, but it's not an object`);
});
}
else if (graphql.isObjectType(type) || graphql.isInterfaceType(type)) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
// this is for isTypeOf and resolveType and all the other stuff.
type[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
const fields = type.getFields();
const field = fields[fieldName];
if (field == null) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${typeName}.${fieldName} defined in resolvers, but not in schema`);
}
throw new Error(`${type.name}.${fieldName} was defined in resolvers, but ${type.name} is not an object or interface type`);
});
return new graphql.GraphQLUnionType(config);
}
},
[utils.MapperKind.OBJECT_TYPE]: type => {
const resolverValue = resolvers[type.name];
if (resolverValue != null) {
const config = type.toConfig();
const fields = config.fields;
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
const field = fields[fieldName];
if (field == null) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${type.name}.${fieldName} defined in resolvers, but not in schema`);
}
});
return new graphql.GraphQLObjectType(config);
}
},
[utils.MapperKind.INTERFACE_TYPE]: type => {
const resolverValue = resolvers[type.name];
if (resolverValue != null) {
const config = type.toConfig();
const fields = config.fields;
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
const field = fields[fieldName];
if (field == null) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${type.name}.${fieldName} defined in resolvers, but not in schema`);
}
});
return new graphql.GraphQLInterfaceType(config);
}
},
[utils.MapperKind.COMPOSITE_FIELD]: (fieldConfig, fieldName, typeName) => {
const resolverValue = resolvers[typeName];
if (resolverValue != null) {
const fieldResolve = resolverValue[fieldName];
if (typeof fieldResolve === 'function') {
// for convenience. Allows shorter syntax in resolver definition file
field.resolve = fieldResolve;
}
else {
if (typeof fieldResolve !== 'object') {
throw new Error(`Resolver ${typeName}.${fieldName} must be object or function`);
if (fieldResolve != null) {
const newFieldConfig = { ...fieldConfig };
if (typeof fieldResolve === 'function') {
// for convenience. Allows shorter syntax in resolver definition file
newFieldConfig.resolve = fieldResolve;
}
setFieldProperties(field, fieldResolve);
else {
if (typeof fieldResolve !== 'object') {
throw new Error(`Resolver ${typeName}.${fieldName} must be object or function`);
}
setFieldProperties(newFieldConfig, fieldResolve);
}
return newFieldConfig;
}
});
}
}
},
});
checkForResolveTypeResolver(schema, requireResolversForResolveType);
// serialize all default values prior to healing fields with new scalar/enum types.
utils.forEachDefaultValue(schema, utils.serializeInputValue);
// schema may have new scalar/enum types that require healing
utils.healSchema(schema);
// reparse all default values with new parsing functions.
utils.forEachDefaultValue(schema, utils.parseInputValue);
if (defaultFieldResolver != null) {
utils.forEachField(schema, field => {
if (!field.resolve) {
field.resolve = defaultFieldResolver;
}
schema = utils.mapSchema(schema, {
[utils.MapperKind.OBJECT_FIELD]: fieldConfig => ({
...fieldConfig,
resolve: fieldConfig.resolve != null ? fieldConfig.resolve : defaultFieldResolver,
}),
});

@@ -459,5 +530,7 @@ }

}
utils.forEachField(schema, (field, typeName, fieldName) => {
const errorHint = `${typeName}.${fieldName}`;
field.resolve = decorateWithLogger(field.resolve, logger, errorHint);
return utils.mapSchema(schema, {
[utils.MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName) => ({
...fieldConfig,
resolve: decorateWithLogger(fieldConfig.resolve, logger, `${typeName}.${fieldName}`),
}),
});

@@ -477,9 +550,11 @@ }

function addCatchUndefinedToSchema(schema) {
utils.forEachField(schema, (field, typeName, fieldName) => {
const errorHint = `${typeName}.${fieldName}`;
field.resolve = decorateToCatchUndefined(field.resolve, errorHint);
return utils.mapSchema(schema, {
[utils.MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName) => ({
...fieldConfig,
resolve: decorateToCatchUndefined(fieldConfig.resolve, `${typeName}.${fieldName}`),
}),
});
}
function makeExecutableSchema({ typeDefs, resolvers = {}, logger, allowUndefinedInResolve = true, resolverValidationOptions = {}, directiveResolvers, schemaDirectives, parseOptions = {}, inheritResolversFromInterfaces = false, }) {
function makeExecutableSchema({ typeDefs, resolvers = {}, logger, allowUndefinedInResolve = true, resolverValidationOptions = {}, directiveResolvers, schemaDirectives, schemaTransforms = [], parseOptions = {}, inheritResolversFromInterfaces = false, }) {
// Validate and clean up arguments

@@ -493,8 +568,6 @@ if (typeof resolverValidationOptions !== 'object') {

// We allow passing in an array of resolver maps, in which case we merge them
const resolverMap = Array.isArray(resolvers)
? resolvers.filter(resolverObj => typeof resolverObj === 'object').reduce(utils.mergeDeep, {})
: resolvers;
const resolverMap = Array.isArray(resolvers) ? resolvers.reduce(utils.mergeDeep, {}) : resolvers;
// Arguments are now validated and cleaned up
const schema = buildSchemaFromTypeDefinitions(typeDefs, parseOptions);
addResolversToSchema({
let schema = buildSchemaFromTypeDefinitions(typeDefs, parseOptions);
schema = addResolversToSchema({
schema,

@@ -507,6 +580,6 @@ resolvers: resolverMap,

if (!allowUndefinedInResolve) {
addCatchUndefinedToSchema(schema);
schema = addCatchUndefinedToSchema(schema);
}
if (logger != null) {
addErrorLoggingToSchema(schema, logger);
schema = addErrorLoggingToSchema(schema, logger);
}

@@ -516,6 +589,11 @@ if (typeof resolvers['__schema'] === 'function') {

// not doing that now, because I'd have to rewrite a lot of tests.
addSchemaLevelResolver(schema, resolvers['__schema']);
schema = addSchemaLevelResolver(schema, resolvers['__schema']);
}
schemaTransforms.forEach(schemaTransform => {
schema = schemaTransform(schema);
});
// directive resolvers are implemented using SchemaDirectiveVisitor.visitSchemaDirectives
// schema visiting modifies the schema in place
if (directiveResolvers != null) {
attachDirectiveResolvers(schema, directiveResolvers);
schema = attachDirectiveResolvers(schema, directiveResolvers);
}

@@ -522,0 +600,0 @@ if (schemaDirectives != null) {

@@ -1,3 +0,3 @@

import { defaultFieldResolver, isScalarType, getNamedType, Kind, print, buildASTSchema, extendSchema, parse, isAbstractType, isSchema, isEnumType, GraphQLEnumType, isUnionType, isObjectType, isInterfaceType } from 'graphql';
import { forEachField, SchemaDirectiveVisitor, forEachDefaultValue, serializeInputValue, healSchema, parseInputValue, mergeDeep } from '@graphql-tools/utils';
import { defaultFieldResolver, isScalarType, getNamedType, Kind, print, buildASTSchema, extendSchema, parse, isAbstractType, isSchema, isSpecifiedScalarType, GraphQLScalarType, GraphQLEnumType, GraphQLUnionType, GraphQLObjectType, GraphQLInterfaceType } from 'graphql';
import { mapSchema, MapperKind, forEachField, getDirectives, mergeDeep, SchemaDirectiveVisitor } from '@graphql-tools/utils';

@@ -8,20 +8,21 @@ // wraps all resolvers of query, mutation or subscription fields

// TODO test that schema is a schema, fn is a function
const rootTypes = [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()].filter(x => Boolean(x));
rootTypes.forEach(type => {
if (type != null) {
const fnToRunOnlyOnce = runAtMostOncePerRequest(fn);
return mapSchema(schema, {
[MapperKind.ROOT_FIELD]: (fieldConfig, _fieldName, typeName, schema) => {
// XXX this should run at most once per request to simulate a true root resolver
// for graphql-js this is an approximation that works with queries but not mutations
const rootResolveFn = runAtMostOncePerRequest(fn);
const fields = type.getFields();
Object.keys(fields).forEach(fieldName => {
// XXX if the type is a subscription, a same query AST will be ran multiple times so we
// deactivate here the runOnce if it's a subscription. This may not be optimal though...
if (type === schema.getSubscriptionType()) {
fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, fn);
}
else {
fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, rootResolveFn);
}
});
}
// XXX if the type is a subscription, a same query AST will be ran multiple times so we
// deactivate here the runOnce if it's a subscription. This may not be optimal though...
const subscription = schema.getSubscriptionType();
if (subscription != null && subscription.name === typeName) {
return {
...fieldConfig,
resolve: wrapResolver(fieldConfig.resolve, fn),
};
}
return {
...fieldConfig,
resolve: wrapResolver(fieldConfig.resolve, fnToRunOnlyOnce),
};
},
});

@@ -117,23 +118,25 @@ }

}
const schemaDirectives = Object.create(null);
Object.keys(directiveResolvers).forEach(directiveName => {
schemaDirectives[directiveName] = class extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const resolver = directiveResolvers[directiveName];
const originalResolver = field.resolve != null ? field.resolve : defaultFieldResolver;
const directiveArgs = this.args;
field.resolve = (...args) => {
const [source /* original args */, , context, info] = args;
return resolver(() => new Promise((resolve, reject) => {
const result = originalResolver.apply(field, args);
if (result instanceof Error) {
reject(result);
}
resolve(result);
}), source, directiveArgs, context, info);
};
}
};
return mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: fieldConfig => {
const newFieldConfig = { ...fieldConfig };
const directives = getDirectives(schema, fieldConfig);
Object.keys(directives).forEach(directiveName => {
if (directiveResolvers[directiveName]) {
const resolver = directiveResolvers[directiveName];
const originalResolver = newFieldConfig.resolve != null ? newFieldConfig.resolve : defaultFieldResolver;
const directiveArgs = directives[directiveName];
newFieldConfig.resolve = (source, originalArgs, context, info) => {
return resolver(() => new Promise((resolve, reject) => {
const result = originalResolver(source, originalArgs, context, info);
if (result instanceof Error) {
reject(result);
}
resolve(result);
}), source, directiveArgs, context, info);
};
}
});
return newFieldConfig;
},
});
SchemaDirectiveVisitor.visitSchemaDirectives(schema, schemaDirectives);
}

@@ -301,10 +304,27 @@

typeNames.forEach(typeName => {
const typeResolvers = resolvers[typeName];
const type = schema.getType(typeName);
if ('getInterfaces' in type) {
const interfaceResolvers = type.getInterfaces().map(iFace => resolvers[iFace.name]);
extendedResolvers[typeName] = Object.assign({}, ...interfaceResolvers, typeResolvers);
const allInterfaceResolvers = type
.getInterfaces()
.map(iFace => resolvers[iFace.name])
.filter(interfaceResolvers => interfaceResolvers != null);
extendedResolvers[typeName] = {};
allInterfaceResolvers.forEach(interfaceResolvers => {
Object.keys(interfaceResolvers).forEach(fieldName => {
if (fieldName === '__isTypeOf' || !fieldName.startsWith('__')) {
extendedResolvers[typeName][fieldName] = interfaceResolvers[fieldName];
}
});
});
const typeResolvers = resolvers[typeName];
extendedResolvers[typeName] = {
...extendedResolvers[typeName],
...typeResolvers,
};
}
else if (typeResolvers != null) {
extendedResolvers[typeName] = typeResolvers;
else {
const typeResolvers = resolvers[typeName];
if (typeResolvers != null) {
extendedResolvers[typeName] = typeResolvers;
}
}

@@ -323,3 +343,3 @@ });

: schemaOrOptions;
const { schema, resolvers: inputResolvers, defaultFieldResolver, resolverValidationOptions = {}, inheritResolversFromInterfaces = false, } = options;
let { schema, resolvers: inputResolvers, defaultFieldResolver, resolverValidationOptions = {}, inheritResolversFromInterfaces = false, } = options;
const { allowResolversNotInSchema = false, requireResolversForResolveType } = resolverValidationOptions;

@@ -329,110 +349,161 @@ const resolvers = inheritResolversFromInterfaces

: inputResolvers;
const typeMap = schema.getTypeMap();
Object.keys(resolvers).forEach(typeName => {
const resolverValue = resolvers[typeName];
const resolverType = typeof resolverValue;
if (resolverType !== 'object' && resolverType !== 'function') {
throw new Error(`"${typeName}" defined in resolvers, but has invalid value "${resolverValue}". A resolver's value must be of type object or function.`);
if (typeName === '__schema') {
if (resolverType !== 'function') {
throw new Error(`"${typeName}" defined in resolvers, but has invalid value "${resolverValue}". A schema resolver's value must be of type object or function.`);
}
}
const type = schema.getType(typeName);
if (!type && typeName !== '__schema') {
if (allowResolversNotInSchema) {
return;
else {
if (resolverType !== 'object') {
throw new Error(`"${typeName}" defined in resolvers, but has invalid value "${resolverValue}". The resolver's value must be of type object.`);
}
throw new Error(`"${typeName}" defined in resolvers, but not in schema`);
}
if (isScalarType(type)) {
// Support -- without recommending -- overriding default scalar types
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
type[fieldName.substring(2)] = resolverValue[fieldName];
const type = schema.getType(typeName);
if (type == null) {
if (allowResolversNotInSchema) {
return;
}
else {
type[fieldName] = resolverValue[fieldName];
}
});
throw new Error(`"${typeName}" defined in resolvers, but not in schema`);
}
else if (isSpecifiedScalarType(type)) {
// allow -- without recommending -- overriding of specified scalar types
const resolverValue = resolvers[typeName];
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
type[fieldName.substring(2)] = resolverValue[fieldName];
}
else {
type[fieldName] = resolverValue[fieldName];
}
});
}
}
else if (isEnumType(type)) {
// We've encountered an enum resolver that is being used to provide an
// internal enum value.
// Reference: https://www.apollographql.com/docs/graphql-tools/scalars.html#internal-values
Object.keys(resolverValue).forEach(fieldName => {
if (!type.getValue(fieldName)) {
if (allowResolversNotInSchema) {
});
schema = mapSchema(schema, {
[MapperKind.SCALAR_TYPE]: type => {
const config = type.toConfig();
const resolverValue = resolvers[type.name];
if (!isSpecifiedScalarType(type) && resolverValue != null) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
}
else {
config[fieldName] = resolverValue[fieldName];
}
});
return new GraphQLScalarType(config);
}
},
[MapperKind.ENUM_TYPE]: type => {
const resolverValue = resolvers[type.name];
const config = type.toConfig();
const enumValueConfigMap = config.values;
if (resolverValue != null) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
}
else if (!enumValueConfigMap[fieldName]) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${type.name}.${fieldName} was defined in resolvers, but not present within ${type.name}`);
}
else {
enumValueConfigMap[fieldName].value = resolverValue[fieldName];
}
});
return new GraphQLEnumType(config);
}
},
[MapperKind.UNION_TYPE]: type => {
const resolverValue = resolvers[type.name];
if (resolverValue != null) {
const config = type.toConfig();
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
// this is for isTypeOf and resolveType and all the other stuff.
config[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
throw new Error(`${typeName}.${fieldName} was defined in resolvers, but enum is not in schema`);
}
});
const config = type.toConfig();
const values = type.getValues();
const newValues = values.reduce((prev, value) => ({
...prev,
[value.name]: {
value: Object.keys(resolverValue).includes(value.name) ? resolverValue[value.name] : value.name,
deprecationReason: value.deprecationReason,
description: value.description,
astNode: value.astNode,
},
}), {});
// healSchema called later to update all fields to new type
typeMap[typeName] = new GraphQLEnumType({
...config,
values: newValues,
});
}
else if (isUnionType(type)) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
// this is for isTypeOf and resolveType and all the other stuff.
type[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${typeName} was defined in resolvers, but it's not an object`);
});
}
else if (isObjectType(type) || isInterfaceType(type)) {
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
// this is for isTypeOf and resolveType and all the other stuff.
type[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
const fields = type.getFields();
const field = fields[fieldName];
if (field == null) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${typeName}.${fieldName} defined in resolvers, but not in schema`);
}
throw new Error(`${type.name}.${fieldName} was defined in resolvers, but ${type.name} is not an object or interface type`);
});
return new GraphQLUnionType(config);
}
},
[MapperKind.OBJECT_TYPE]: type => {
const resolverValue = resolvers[type.name];
if (resolverValue != null) {
const config = type.toConfig();
const fields = config.fields;
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
const field = fields[fieldName];
if (field == null) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${type.name}.${fieldName} defined in resolvers, but not in schema`);
}
});
return new GraphQLObjectType(config);
}
},
[MapperKind.INTERFACE_TYPE]: type => {
const resolverValue = resolvers[type.name];
if (resolverValue != null) {
const config = type.toConfig();
const fields = config.fields;
Object.keys(resolverValue).forEach(fieldName => {
if (fieldName.startsWith('__')) {
config[fieldName.substring(2)] = resolverValue[fieldName];
return;
}
const field = fields[fieldName];
if (field == null) {
if (allowResolversNotInSchema) {
return;
}
throw new Error(`${type.name}.${fieldName} defined in resolvers, but not in schema`);
}
});
return new GraphQLInterfaceType(config);
}
},
[MapperKind.COMPOSITE_FIELD]: (fieldConfig, fieldName, typeName) => {
const resolverValue = resolvers[typeName];
if (resolverValue != null) {
const fieldResolve = resolverValue[fieldName];
if (typeof fieldResolve === 'function') {
// for convenience. Allows shorter syntax in resolver definition file
field.resolve = fieldResolve;
}
else {
if (typeof fieldResolve !== 'object') {
throw new Error(`Resolver ${typeName}.${fieldName} must be object or function`);
if (fieldResolve != null) {
const newFieldConfig = { ...fieldConfig };
if (typeof fieldResolve === 'function') {
// for convenience. Allows shorter syntax in resolver definition file
newFieldConfig.resolve = fieldResolve;
}
setFieldProperties(field, fieldResolve);
else {
if (typeof fieldResolve !== 'object') {
throw new Error(`Resolver ${typeName}.${fieldName} must be object or function`);
}
setFieldProperties(newFieldConfig, fieldResolve);
}
return newFieldConfig;
}
});
}
}
},
});
checkForResolveTypeResolver(schema, requireResolversForResolveType);
// serialize all default values prior to healing fields with new scalar/enum types.
forEachDefaultValue(schema, serializeInputValue);
// schema may have new scalar/enum types that require healing
healSchema(schema);
// reparse all default values with new parsing functions.
forEachDefaultValue(schema, parseInputValue);
if (defaultFieldResolver != null) {
forEachField(schema, field => {
if (!field.resolve) {
field.resolve = defaultFieldResolver;
}
schema = mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: fieldConfig => ({
...fieldConfig,
resolve: fieldConfig.resolve != null ? fieldConfig.resolve : defaultFieldResolver,
}),
});

@@ -455,5 +526,7 @@ }

}
forEachField(schema, (field, typeName, fieldName) => {
const errorHint = `${typeName}.${fieldName}`;
field.resolve = decorateWithLogger(field.resolve, logger, errorHint);
return mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName) => ({
...fieldConfig,
resolve: decorateWithLogger(fieldConfig.resolve, logger, `${typeName}.${fieldName}`),
}),
});

@@ -473,9 +546,11 @@ }

function addCatchUndefinedToSchema(schema) {
forEachField(schema, (field, typeName, fieldName) => {
const errorHint = `${typeName}.${fieldName}`;
field.resolve = decorateToCatchUndefined(field.resolve, errorHint);
return mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName) => ({
...fieldConfig,
resolve: decorateToCatchUndefined(fieldConfig.resolve, `${typeName}.${fieldName}`),
}),
});
}
function makeExecutableSchema({ typeDefs, resolvers = {}, logger, allowUndefinedInResolve = true, resolverValidationOptions = {}, directiveResolvers, schemaDirectives, parseOptions = {}, inheritResolversFromInterfaces = false, }) {
function makeExecutableSchema({ typeDefs, resolvers = {}, logger, allowUndefinedInResolve = true, resolverValidationOptions = {}, directiveResolvers, schemaDirectives, schemaTransforms = [], parseOptions = {}, inheritResolversFromInterfaces = false, }) {
// Validate and clean up arguments

@@ -489,8 +564,6 @@ if (typeof resolverValidationOptions !== 'object') {

// We allow passing in an array of resolver maps, in which case we merge them
const resolverMap = Array.isArray(resolvers)
? resolvers.filter(resolverObj => typeof resolverObj === 'object').reduce(mergeDeep, {})
: resolvers;
const resolverMap = Array.isArray(resolvers) ? resolvers.reduce(mergeDeep, {}) : resolvers;
// Arguments are now validated and cleaned up
const schema = buildSchemaFromTypeDefinitions(typeDefs, parseOptions);
addResolversToSchema({
let schema = buildSchemaFromTypeDefinitions(typeDefs, parseOptions);
schema = addResolversToSchema({
schema,

@@ -503,6 +576,6 @@ resolvers: resolverMap,

if (!allowUndefinedInResolve) {
addCatchUndefinedToSchema(schema);
schema = addCatchUndefinedToSchema(schema);
}
if (logger != null) {
addErrorLoggingToSchema(schema, logger);
schema = addErrorLoggingToSchema(schema, logger);
}

@@ -512,6 +585,11 @@ if (typeof resolvers['__schema'] === 'function') {

// not doing that now, because I'd have to rewrite a lot of tests.
addSchemaLevelResolver(schema, resolvers['__schema']);
schema = addSchemaLevelResolver(schema, resolvers['__schema']);
}
schemaTransforms.forEach(schemaTransform => {
schema = schemaTransform(schema);
});
// directive resolvers are implemented using SchemaDirectiveVisitor.visitSchemaDirectives
// schema visiting modifies the schema in place
if (directiveResolvers != null) {
attachDirectiveResolvers(schema, directiveResolvers);
schema = attachDirectiveResolvers(schema, directiveResolvers);
}

@@ -518,0 +596,0 @@ if (schemaDirectives != null) {

import { IExecutableSchemaDefinition } from './types';
export declare function makeExecutableSchema<TContext = any>({ typeDefs, resolvers, logger, allowUndefinedInResolve, resolverValidationOptions, directiveResolvers, schemaDirectives, parseOptions, inheritResolversFromInterfaces, }: IExecutableSchemaDefinition<TContext>): import("graphql").GraphQLSchema;
export declare function makeExecutableSchema<TContext = any>({ typeDefs, resolvers, logger, allowUndefinedInResolve, resolverValidationOptions, directiveResolvers, schemaDirectives, schemaTransforms, parseOptions, inheritResolversFromInterfaces, }: IExecutableSchemaDefinition<TContext>): import("graphql").GraphQLSchema;
{
"name": "@graphql-tools/schema",
"version": "5.0.1-alpha-ecad9d5.0",
"version": "5.0.1-alpha-f4c5dfe.0",
"description": "A set of utils for faster development of GraphQL tools",

@@ -9,3 +9,3 @@ "peerDependencies": {

"dependencies": {
"@graphql-tools/utils": "5.0.1-alpha-ecad9d5.0",
"@graphql-tools/utils": "5.0.1-alpha-f4c5dfe.0",
"tslib": "1.11.1"

@@ -12,0 +12,0 @@ },

@@ -1,2 +0,2 @@

import { ITypeDefinitions, IResolvers, IResolverValidationOptions, IDirectiveResolvers, SchemaDirectiveVisitorClass, GraphQLParseOptions } from 'packages/utils/src';
import { ITypeDefinitions, IResolvers, IResolverValidationOptions, IDirectiveResolvers, SchemaDirectiveVisitorClass, GraphQLParseOptions, SchemaTransform } from '@graphql-tools/utils';
export interface ILogger {

@@ -13,4 +13,5 @@ log: (error: Error) => void;

schemaDirectives?: Record<string, SchemaDirectiveVisitorClass>;
schemaTransforms?: Array<SchemaTransform>;
parseOptions?: GraphQLParseOptions;
inheritResolversFromInterfaces?: boolean;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc