@apollo/federation-internals
Advanced tools
Comparing version 2.0.0-preview.9 to 2.0.0-preview.10
# CHANGELOG for `@apollo/federation-internals` | ||
## v2.0.0-preview.10 | ||
- Released in sync with other federation packages but no changes to this package. | ||
## v2.0.0-preview.9 | ||
@@ -4,0 +8,0 @@ |
@@ -52,2 +52,4 @@ import { ConstArgumentNode, ASTNode, DirectiveLocation, ConstDirectiveNode, DocumentNode, GraphQLError, GraphQLSchema, TypeNode, VariableDefinitionNode, VariableNode } from "graphql"; | ||
export declare function isInputType(type: Type): type is InputType; | ||
export declare function isTypeOfKind<T extends Type>(type: Type, kind: T['kind']): type is T; | ||
export declare function filterTypesOfKind<T extends Type>(types: readonly Type[], kind: T['kind']): T[]; | ||
export declare function baseType(type: Type): NamedType; | ||
@@ -89,5 +91,5 @@ export declare function isNullableType(type: Type): boolean; | ||
} | ||
export declare function sourceASTs(...elts: ({ | ||
sourceAST?: ASTNode; | ||
} | undefined)[]): ASTNode[]; | ||
export declare function sourceASTs<TNode extends ASTNode = ASTNode>(...elts: ({ | ||
sourceAST?: TNode; | ||
} | undefined)[]): TNode[]; | ||
declare abstract class Element<TParent extends SchemaElement<any, any> | Schema | DirectiveTargetElement<any>> { | ||
@@ -252,6 +254,12 @@ protected _parent?: TParent; | ||
get schemaDefinition(): SchemaDefinition; | ||
types<T extends NamedType>(kind?: T['kind']): readonly T[]; | ||
builtInTypes<T extends NamedType>(kind?: T['kind'], includeShadowed?: boolean): readonly T[]; | ||
types(): readonly NamedType[]; | ||
interfaceTypes(): readonly InterfaceType[]; | ||
objectTypes(): readonly ObjectType[]; | ||
unionTypes(): readonly UnionType[]; | ||
scalarTypes(): readonly ScalarType[]; | ||
inputTypes(): readonly InputObjectType[]; | ||
enumTypes(): readonly EnumType[]; | ||
builtInTypes(includeShadowed?: boolean): readonly NamedType[]; | ||
private isShadowedBuiltInType; | ||
allTypes<T extends NamedType>(kind?: T['kind']): readonly T[]; | ||
allTypes(): readonly NamedType[]; | ||
type(name: string): NamedType | undefined; | ||
@@ -258,0 +266,0 @@ typeOfKind<T extends NamedType>(name: string, kind: T['kind']): T | undefined; |
@@ -221,3 +221,3 @@ "use strict"; | ||
} | ||
if (!(0, types_1.sameType)(type, actualType)) { | ||
if (!(0, types_1.sameType)(type, actualType) && !isValidInputTypeRedefinition(type, actualType)) { | ||
errors.push(error_1.ERRORS.DIRECTIVE_DEFINITION_INVALID.err({ | ||
@@ -245,2 +245,11 @@ message: `Invalid definition for ${what}: argument "${name}" should have type "${type}" but found type "${actualArgument.type}"`, | ||
} | ||
function isValidInputTypeRedefinition(expectedType, actualType) { | ||
if ((0, definitions_1.isListType)(expectedType)) { | ||
return (0, definitions_1.isListType)(actualType) && isValidInputTypeRedefinition(expectedType.ofType, actualType.ofType); | ||
} | ||
if ((0, definitions_1.isNonNullType)(expectedType)) { | ||
return (0, definitions_1.isNonNullType)(actualType) && isValidInputTypeRedefinition(expectedType.ofType, actualType.ofType); | ||
} | ||
return (0, definitions_1.isCustomScalarType)(expectedType) && !(0, definitions_1.isCustomScalarType)(actualType); | ||
} | ||
//# sourceMappingURL=directiveAndTypeSpecification.js.map |
@@ -100,2 +100,6 @@ import { ASTNode, GraphQLError, Source } from "graphql"; | ||
REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH: ErrorCodeDefinition; | ||
REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH: ErrorCodeDefinition; | ||
EMPTY_MERGED_INPUT_TYPE: ErrorCodeDefinition; | ||
INCONSISTENT_ENUM_VALUE: ErrorCodeDefinition; | ||
EMPTY_MERGED_ENUM_TYPE: ErrorCodeDefinition; | ||
SATISFIABILITY_ERROR: ErrorCodeDefinition; | ||
@@ -102,0 +106,0 @@ OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE: ErrorCodeDefinition; |
@@ -117,3 +117,7 @@ "use strict"; | ||
const REFERENCED_INACCESSIBLE = makeCodeDefinition('REFERENCED_INACCESSIBLE', 'An element is marked as @inaccessible but is referenced by a non-inaccessible element.'); | ||
const REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH = makeCodeDefinition('REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH', 'An argument of a field or directive definition is mandatory in some subgraphs, but the argument is not defined in all subgraphs that define the field or directive definition.'); | ||
const REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH = makeCodeDefinition('REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH', 'A field of an input object type is mandatory in some subgraphs, but the field is not defined in all the subgraphs that define the input object type.'); | ||
const REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH = makeCodeDefinition('REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH', 'An argument of a field or directive definition is mandatory in some subgraphs, but the argument is not defined in all the subgraphs that define the field or directive definition.'); | ||
const EMPTY_MERGED_INPUT_TYPE = makeCodeDefinition('EMPTY_MERGED_INPUT_TYPE', 'An input object type has no field common to all the subgraphs that define the type. Merging that type would result in an invalid empty input object type.'); | ||
const INCONSISTENT_ENUM_VALUE = makeCodeDefinition('INCONSISTENT_ENUM_VALUE', 'An enum type that is used as both an input and output type has a value that is not defined in all the subgraphs that define the enum type.'); | ||
const EMPTY_MERGED_ENUM_TYPE = makeCodeDefinition('EMPTY_MERGED_ENUM_TYPE', 'An enum type has no value common to all the subgraphs that define the type. Merging that type would result in an invalid empty enum type.'); | ||
const SATISFIABILITY_ERROR = makeCodeDefinition('SATISFIABILITY_ERROR', 'Subgraphs can be merged, but the resulting supergraph API would have queries that cannot be satisfied by those subgraphs.'); | ||
@@ -180,2 +184,6 @@ const OVERRIDE_FROM_SELF_ERROR = makeCodeDefinition('OVERRIDE_FROM_SELF_ERROR', 'Field with `@override` directive has "from" location that references its own subgraph.'); | ||
REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH, | ||
REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH, | ||
EMPTY_MERGED_INPUT_TYPE, | ||
INCONSISTENT_ENUM_VALUE, | ||
EMPTY_MERGED_ENUM_TYPE, | ||
SATISFIABILITY_ERROR, | ||
@@ -182,0 +190,0 @@ OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE, |
@@ -201,3 +201,3 @@ "use strict"; | ||
for (const subgraph of subgraphs) { | ||
for (const itf of subgraph.schema.types('InterfaceType')) { | ||
for (const itf of subgraph.schema.interfaceTypes()) { | ||
const implementations = itf.possibleRuntimeTypes(); | ||
@@ -204,0 +204,0 @@ for (const field of itf.fields()) { |
@@ -161,3 +161,3 @@ "use strict"; | ||
}, usedFields); | ||
for (const itfType of metadata.schema.types('InterfaceType')) { | ||
for (const itfType of metadata.schema.interfaceTypes()) { | ||
const runtimeTypes = itfType.possibleRuntimeTypes(); | ||
@@ -208,3 +208,3 @@ for (const field of itfType.fields()) { | ||
function validateNoExternalOnInterfaceFields(metadata, errorCollector) { | ||
for (const itf of metadata.schema.types('InterfaceType')) { | ||
for (const itf of metadata.schema.interfaceTypes()) { | ||
for (const field of itf.fields()) { | ||
@@ -513,3 +513,3 @@ if (metadata.isFieldExternal(field)) { | ||
} | ||
for (const itf of schema.types('InterfaceType')) { | ||
for (const itf of schema.interfaceTypes()) { | ||
validateInterfaceRuntimeImplementationFieldsTypes(itf, metadata, errors); | ||
@@ -908,3 +908,3 @@ } | ||
membersFct: (schema) => { | ||
return schema.types("ObjectType").filter(isEntityType).map((t) => t.name); | ||
return schema.objectTypes().filter(isEntityType).map((t) => t.name); | ||
}, | ||
@@ -911,0 +911,0 @@ }); |
@@ -22,3 +22,3 @@ "use strict"; | ||
}; | ||
for (const type of schema.types('ObjectType')) { | ||
for (const type of schema.objectTypes()) { | ||
addKeyFields(type); | ||
@@ -46,3 +46,3 @@ const shareablesOnType = shareableDirective ? type.appliedDirectivesOf(shareableDirective) : []; | ||
} | ||
for (const type of schema.types('InterfaceType')) { | ||
for (const type of schema.interfaceTypes()) { | ||
addKeyFields(type); | ||
@@ -49,0 +49,0 @@ } |
@@ -317,3 +317,3 @@ "use strict"; | ||
removeExternalOnInterface() { | ||
for (const itf of this.schema.types('InterfaceType')) { | ||
for (const itf of this.schema.interfaceTypes()) { | ||
for (const field of itf.fields()) { | ||
@@ -443,3 +443,3 @@ const external = this.external(field); | ||
removeDirectivesOnInterface() { | ||
for (const type of this.schema.types('InterfaceType')) { | ||
for (const type of this.schema.interfaceTypes()) { | ||
for (const application of type.appliedDirectivesOf(this.metadata.keyDirective())) { | ||
@@ -460,3 +460,3 @@ this.addChange(new KeyOnInterfaceRemoval(type.name)); | ||
removeProvidesOnNonComposite() { | ||
for (const type of this.schema.types('ObjectType')) { | ||
for (const type of this.schema.objectTypes()) { | ||
for (const field of type.fields()) { | ||
@@ -477,3 +477,3 @@ if ((0, definitions_1.isCompositeType)((0, definitions_1.baseType)(field.type))) { | ||
const shareableDirective = this.metadata.shareableDirective(); | ||
for (const type of this.schema.types('ObjectType')) { | ||
for (const type of this.schema.objectTypes()) { | ||
if (type.hasAppliedDirective(keyDirective) || type.isRootType()) { | ||
@@ -480,0 +480,0 @@ for (const field of type.fields()) { |
@@ -101,2 +101,3 @@ "use strict"; | ||
} | ||
return !!elt.type; | ||
} | ||
@@ -137,4 +138,3 @@ validateName(elt) { | ||
} | ||
this.validateHasType(itfField); | ||
if (!(0, types_1.isSubtype)(itfField.type, field.type)) { | ||
if (this.validateHasType(itfField) && !(0, types_1.isSubtype)(itfField.type, field.type)) { | ||
this.errors.push(new graphql_1.GraphQLError(`Interface field ${itfField.coordinate} expects type ${itfField.type} but ${field.coordinate} of type ${field.type} is not a proper subtype.`, (0, definitions_1.sourceASTs)(itfField, field))); | ||
@@ -148,4 +148,3 @@ } | ||
} | ||
this.validateHasType(itfArg); | ||
if (!(0, types_1.sameType)(itfArg.type, arg.type)) { | ||
if (this.validateHasType(itfArg) && !(0, types_1.sameType)(itfArg.type, arg.type)) { | ||
this.errors.push(new graphql_1.GraphQLError(`Interface field argument ${itfArg.coordinate} expects type ${itfArg.type} but ${arg.coordinate} is type ${arg.type}.`, (0, definitions_1.sourceASTs)(itfArg, arg))); | ||
@@ -181,3 +180,5 @@ } | ||
this.validateName(field); | ||
this.validateHasType(field); | ||
if (!this.validateHasType(field)) { | ||
continue; | ||
} | ||
if (field.isRequired() && field.isDeprecated()) { | ||
@@ -190,3 +191,5 @@ this.errors.push(new graphql_1.GraphQLError(`Required input field ${field.coordinate} cannot be deprecated.`, (0, definitions_1.sourceASTs)(field.appliedDirectivesOf('deprecated')[0], field))); | ||
this.validateName(arg); | ||
this.validateHasType(arg); | ||
if (!this.validateHasType(arg)) { | ||
return; | ||
} | ||
if (arg.isRequired() && arg.isDeprecated()) { | ||
@@ -221,3 +224,3 @@ this.errors.push(new graphql_1.GraphQLError(`Required argument ${arg.coordinate} cannot be deprecated.`, (0, definitions_1.sourceASTs)(arg.appliedDirectivesOf('deprecated')[0], arg))); | ||
} | ||
if (!(0, values_1.isValidValue)(value, argument, this.emptyVariables)) { | ||
if (argument.type && !(0, values_1.isValidValue)(value, argument, this.emptyVariables)) { | ||
const parent = application.parent; | ||
@@ -224,0 +227,0 @@ const parentDesc = parent instanceof definitions_1.NamedSchemaElement |
{ | ||
"name": "@apollo/federation-internals", | ||
"version": "2.0.0-preview.9", | ||
"version": "2.0.0-preview.10", | ||
"description": "Apollo Federation internal utilities", | ||
@@ -36,3 +36,3 @@ "main": "dist/index.js", | ||
}, | ||
"gitHead": "dd5ea3a7675af3e19e82d8150f72fe217074ae02" | ||
"gitHead": "08b6f94e15020077ff2a88fbf2f000124d307ecd" | ||
} |
@@ -836,3 +836,3 @@ import { DocumentNode } from 'graphql'; | ||
directive @key(fields: Int!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE | ||
directive @key(fields: String!, resolvable: String) repeatable on OBJECT | INTERFACE | ||
`; | ||
@@ -842,3 +842,3 @@ | ||
'DIRECTIVE_DEFINITION_INVALID', | ||
'[S] Invalid definition for directive "@key": argument "fields" should have type "federation__FieldSet!" but found type "Int!"', | ||
'[S] Invalid definition for directive "@key": argument "resolvable" should have type "Boolean" but found type "String"', | ||
]]); | ||
@@ -866,2 +866,19 @@ }); | ||
}); | ||
it('allows any (non-scalar) type in redefinition when expected type is a scalar', () => { | ||
const doc = gql` | ||
extend schema | ||
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"]) | ||
type T @key(fields: "k") { | ||
k: ID! | ||
} | ||
# 'fields' should be of type 'federation_FieldSet!', but ensure we allow 'String!' alternatively. | ||
directive @key(fields: String!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE | ||
`; | ||
// Just making sure this don't error out. | ||
buildAndValidate(doc); | ||
}); | ||
}); |
@@ -7,3 +7,5 @@ import { ASTNode, DirectiveLocation, GraphQLError } from "graphql"; | ||
InputType, | ||
isCustomScalarType, | ||
isEnumType, | ||
isListType, | ||
isNonNullType, | ||
@@ -314,3 +316,3 @@ isObjectType, | ||
} | ||
if (!sameType(type, actualType)) { | ||
if (!sameType(type, actualType) && !isValidInputTypeRedefinition(type, actualType)) { | ||
errors.push(ERRORS.DIRECTIVE_DEFINITION_INVALID.err({ | ||
@@ -339,1 +341,16 @@ message: `Invalid definition for ${what}: argument "${name}" should have type "${type}" but found type "${actualArgument.type!}"`, | ||
function isValidInputTypeRedefinition(expectedType: InputType, actualType: InputType): boolean { | ||
// If the expected type is a custom scalar, then we allow the redefinition to be another type (unless it's a custom scalar, in which | ||
// case it has to be the same scalar). The rational being that since graphQL does no validation of values passed to a custom scalar, | ||
// any code that gets some value as input for a custom scalar has to do validation manually, and so there is little harm in allowing | ||
// a redefinition with another type since any truly invalid value would failed that "manual validation". In practice, this leeway | ||
// make sense because many scalar will tend to accept only one kind of values (say, strings) and exists only to inform that said string | ||
// needs to follow a specific format, and in such case, letting user redefine the type as String adds flexibility while doing little harm. | ||
if (isListType(expectedType)) { | ||
return isListType(actualType) && isValidInputTypeRedefinition(expectedType.ofType, actualType.ofType); | ||
} | ||
if (isNonNullType(expectedType)) { | ||
return isNonNullType(actualType) && isValidInputTypeRedefinition(expectedType.ofType, actualType.ofType); | ||
} | ||
return isCustomScalarType(expectedType) && !isCustomScalarType(actualType); | ||
} |
@@ -352,7 +352,27 @@ import { ASTNode, GraphQLError, Source } from "graphql"; | ||
const REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH = makeCodeDefinition( | ||
'REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH', | ||
'A field of an input object type is mandatory in some subgraphs, but the field is not defined in all the subgraphs that define the input object type.' | ||
); | ||
const REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH = makeCodeDefinition( | ||
'REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH', | ||
'An argument of a field or directive definition is mandatory in some subgraphs, but the argument is not defined in all subgraphs that define the field or directive definition.' | ||
'An argument of a field or directive definition is mandatory in some subgraphs, but the argument is not defined in all the subgraphs that define the field or directive definition.' | ||
); | ||
const EMPTY_MERGED_INPUT_TYPE = makeCodeDefinition( | ||
'EMPTY_MERGED_INPUT_TYPE', | ||
'An input object type has no field common to all the subgraphs that define the type. Merging that type would result in an invalid empty input object type.' | ||
); | ||
const INCONSISTENT_ENUM_VALUE = makeCodeDefinition( | ||
'INCONSISTENT_ENUM_VALUE', | ||
'An enum type that is used as both an input and output type has a value that is not defined in all the subgraphs that define the enum type.' | ||
); | ||
const EMPTY_MERGED_ENUM_TYPE = makeCodeDefinition( | ||
'EMPTY_MERGED_ENUM_TYPE', | ||
'An enum type has no value common to all the subgraphs that define the type. Merging that type would result in an invalid empty enum type.' | ||
); | ||
const SATISFIABILITY_ERROR = makeCodeDefinition( | ||
@@ -436,2 +456,6 @@ 'SATISFIABILITY_ERROR', | ||
REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH, | ||
REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH, | ||
EMPTY_MERGED_INPUT_TYPE, | ||
INCONSISTENT_ENUM_VALUE, | ||
EMPTY_MERGED_ENUM_TYPE, | ||
SATISFIABILITY_ERROR, | ||
@@ -438,0 +462,0 @@ OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE, |
@@ -271,3 +271,3 @@ import { | ||
for (const subgraph of subgraphs) { | ||
for (const itf of subgraph.schema.types<InterfaceType>('InterfaceType')) { | ||
for (const itf of subgraph.schema.interfaceTypes()) { | ||
// We only look at objects because interfaces are handled by this own loop in practice. | ||
@@ -274,0 +274,0 @@ const implementations = itf.possibleRuntimeTypes(); |
@@ -290,3 +290,3 @@ import { | ||
// Collects all fields used to satisfy an interface constraint | ||
for (const itfType of metadata.schema.types<InterfaceType>('InterfaceType')) { | ||
for (const itfType of metadata.schema.interfaceTypes()) { | ||
const runtimeTypes = itfType.possibleRuntimeTypes(); | ||
@@ -355,3 +355,3 @@ for (const field of itfType.fields()) { | ||
function validateNoExternalOnInterfaceFields(metadata: FederationMetadata, errorCollector: GraphQLError[]) { | ||
for (const itf of metadata.schema.types<InterfaceType>('InterfaceType')) { | ||
for (const itf of metadata.schema.interfaceTypes()) { | ||
for (const field of itf.fields()) { | ||
@@ -777,3 +777,3 @@ if (metadata.isFieldExternal(field)) { | ||
for (const itf of schema.types<InterfaceType>('InterfaceType')) { | ||
for (const itf of schema.interfaceTypes()) { | ||
validateInterfaceRuntimeImplementationFieldsTypes(itf, metadata, errors); | ||
@@ -1256,3 +1256,3 @@ } | ||
membersFct: (schema) => { | ||
return schema.types<ObjectType>("ObjectType").filter(isEntityType).map((t) => t.name); | ||
return schema.objectTypes().filter(isEntityType).map((t) => t.name); | ||
}, | ||
@@ -1259,0 +1259,0 @@ }); |
@@ -8,4 +8,2 @@ import { | ||
collectTargetFields, | ||
InterfaceType, | ||
ObjectType, | ||
Schema, | ||
@@ -37,3 +35,3 @@ } from "."; | ||
for (const type of schema.types<ObjectType>('ObjectType')) { | ||
for (const type of schema.objectTypes()) { | ||
addKeyFields(type); | ||
@@ -64,3 +62,3 @@ const shareablesOnType = shareableDirective ? type.appliedDirectivesOf(shareableDirective) : []; | ||
for (const type of schema.types<InterfaceType>('InterfaceType')) { | ||
for (const type of schema.interfaceTypes()) { | ||
addKeyFields(type); | ||
@@ -67,0 +65,0 @@ } |
@@ -14,3 +14,2 @@ import { | ||
FieldDefinition, | ||
InterfaceType, | ||
isCompositeType, | ||
@@ -438,3 +437,3 @@ isInterfaceType, | ||
private removeExternalOnInterface() { | ||
for (const itf of this.schema.types<InterfaceType>('InterfaceType')) { | ||
for (const itf of this.schema.interfaceTypes()) { | ||
for (const field of itf.fields()) { | ||
@@ -595,3 +594,3 @@ const external = this.external(field); | ||
private removeDirectivesOnInterface() { | ||
for (const type of this.schema.types<InterfaceType>('InterfaceType')) { | ||
for (const type of this.schema.interfaceTypes()) { | ||
for (const application of type.appliedDirectivesOf(this.metadata.keyDirective())) { | ||
@@ -613,3 +612,3 @@ this.addChange(new KeyOnInterfaceRemoval(type.name)); | ||
private removeProvidesOnNonComposite() { | ||
for (const type of this.schema.types<ObjectType>('ObjectType')) { | ||
for (const type of this.schema.objectTypes()) { | ||
for (const field of type.fields()) { | ||
@@ -634,3 +633,3 @@ if (isCompositeType(baseType(field.type!))) { | ||
// - to any (non-external) field of an entity/root-type that is not a key field and if another subgraphs resolve it (fully or partially through @provides) | ||
for (const type of this.schema.types<ObjectType>('ObjectType')) { | ||
for (const type of this.schema.objectTypes()) { | ||
if (type.hasAppliedDirective(keyDirective) || type.isRootType()) { | ||
@@ -637,0 +636,0 @@ for (const field of type.fields()) { |
@@ -132,3 +132,3 @@ import { | ||
private validateHasType(elt: { type?: Type, coordinate: string, sourceAST?: ASTNode }) { | ||
private validateHasType(elt: { type?: Type, coordinate: string, sourceAST?: ASTNode }): boolean { | ||
// Note that this error can't happen if you parse the schema since it wouldn't be valid syntax, but it can happen for | ||
@@ -140,2 +140,3 @@ // programmatically constructed schema. | ||
} | ||
return !!elt.type; | ||
} | ||
@@ -188,4 +189,3 @@ | ||
// as many type as the interface is implemented); it's a cheap check anyway. | ||
this.validateHasType(itfField); | ||
if (!isSubtype(itfField.type!, field.type!)) { | ||
if (this.validateHasType(itfField) && !isSubtype(itfField.type!, field.type!)) { | ||
this.errors.push(new GraphQLError( | ||
@@ -206,6 +206,4 @@ `Interface field ${itfField.coordinate} expects type ${itfField.type} but ${field.coordinate} of type ${field.type} is not a proper subtype.`, | ||
} | ||
// Same as above for the field | ||
this.validateHasType(itfArg); | ||
// Note that we could use contra-variance but as graphQL-js currently doesn't allow it, we mimic that. | ||
if (!sameType(itfArg.type!, arg.type!)) { | ||
if (this.validateHasType(itfArg) && !sameType(itfArg.type!, arg.type!)) { | ||
this.errors.push(new GraphQLError( | ||
@@ -254,3 +252,5 @@ `Interface field argument ${itfArg.coordinate} expects type ${itfArg.type} but ${arg.coordinate} is type ${arg.type}.`, | ||
this.validateName(field); | ||
this.validateHasType(field); | ||
if (!this.validateHasType(field)) { | ||
continue; | ||
} | ||
if (field.isRequired() && field.isDeprecated()) { | ||
@@ -267,3 +267,5 @@ this.errors.push(new GraphQLError( | ||
this.validateName(arg); | ||
this.validateHasType(arg); | ||
if (!this.validateHasType(arg)) { | ||
return; | ||
} | ||
if (arg.isRequired() && arg.isDeprecated()) { | ||
@@ -314,3 +316,6 @@ this.errors.push(new GraphQLError( | ||
} | ||
if (!isValidValue(value, argument, this.emptyVariables)) { | ||
// Note that we validate if the definition argument has a type set separatly | ||
// and log an error if necesary, but we just want to avoid calling | ||
// `isValidValue` if there is not type as it may throw. | ||
if (argument.type && !isValidValue(value, argument, this.emptyVariables)) { | ||
const parent = application.parent; | ||
@@ -317,0 +322,0 @@ // The only non-named SchemaElement is the `schema` definition. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1528096
24895