194 lines
5.9 KiB
JavaScript
194 lines
5.9 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
*
|
|
* @format
|
|
*/
|
|
'use strict';
|
|
|
|
var invariant = require("fbjs/lib/invariant");
|
|
|
|
var nullthrows = require("./nullthrowsOSS");
|
|
|
|
var _require = require("graphql"),
|
|
assertAbstractType = _require.assertAbstractType,
|
|
getNamedType = _require.getNamedType,
|
|
getNullableType = _require.getNullableType,
|
|
isType = _require.isType,
|
|
print = _require.print,
|
|
typeFromAST = _require.typeFromAST,
|
|
GraphQLInterfaceType = _require.GraphQLInterfaceType,
|
|
GraphQLList = _require.GraphQLList,
|
|
GraphQLObjectType = _require.GraphQLObjectType,
|
|
GraphQLSchema = _require.GraphQLSchema,
|
|
GraphQLUnionType = _require.GraphQLUnionType;
|
|
|
|
var ID = 'id';
|
|
var ID_TYPE = 'ID';
|
|
|
|
/**
|
|
* Determine if the given type may implement the named type:
|
|
* - it is the named type
|
|
* - it implements the named interface
|
|
* - it is an abstract type and *some* of its concrete types may
|
|
* implement the named type
|
|
*/
|
|
function mayImplement(schema, type, typeName) {
|
|
var unmodifiedType = getRawType(type);
|
|
return unmodifiedType.toString() === typeName || implementsInterface(unmodifiedType, typeName) || isAbstractType(unmodifiedType) && hasConcreteTypeThatImplements(schema, unmodifiedType, typeName);
|
|
}
|
|
|
|
function canHaveSelections(type) {
|
|
return type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType;
|
|
}
|
|
/**
|
|
* Implements duck typing that checks whether a type has an id field of the ID
|
|
* type. This is approximating what we can hopefully do with the __id proposal
|
|
* a bit more cleanly.
|
|
*
|
|
* https://github.com/graphql/graphql-future/blob/master/01%20-%20__id.md
|
|
*/
|
|
|
|
|
|
function hasID(schema, type) {
|
|
var unmodifiedType = getRawType(type);
|
|
!(unmodifiedType instanceof GraphQLObjectType || unmodifiedType instanceof GraphQLInterfaceType) ? process.env.NODE_ENV !== "production" ? invariant(false, 'GraphQLSchemaUtils.hasID(): Expected a concrete type or interface, ' + 'got type `%s`.', type) : invariant(false) : void 0;
|
|
var idType = schema.getType(ID_TYPE);
|
|
var idField = unmodifiedType.getFields()[ID];
|
|
return idField && getRawType(idField.type) === idType;
|
|
}
|
|
/**
|
|
* Determine if a type is abstract (not concrete).
|
|
*
|
|
* Note: This is used in place of the `graphql` version of the function in order
|
|
* to not break `instanceof` checks with Jest. This version also unwraps
|
|
* non-null/list wrapper types.
|
|
*/
|
|
|
|
|
|
function isAbstractType(type) {
|
|
var rawType = getRawType(type);
|
|
return rawType instanceof GraphQLInterfaceType || rawType instanceof GraphQLUnionType;
|
|
}
|
|
|
|
function isUnionType(type) {
|
|
return type instanceof GraphQLUnionType;
|
|
}
|
|
/**
|
|
* Get the unmodified type, with list/null wrappers removed.
|
|
*/
|
|
|
|
|
|
function getRawType(type) {
|
|
return nullthrows(getNamedType(type));
|
|
}
|
|
/**
|
|
* Gets the non-list type, removing the list wrapper if present.
|
|
*/
|
|
|
|
|
|
function getSingularType(type) {
|
|
var unmodifiedType = type;
|
|
|
|
while (unmodifiedType instanceof GraphQLList) {
|
|
unmodifiedType = unmodifiedType.ofType;
|
|
}
|
|
|
|
return unmodifiedType;
|
|
}
|
|
/**
|
|
* @public
|
|
*/
|
|
|
|
|
|
function implementsInterface(type, interfaceName) {
|
|
return getInterfaces(type).some(function (interfaceType) {
|
|
return interfaceType.toString() === interfaceName;
|
|
});
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
|
|
|
|
function hasConcreteTypeThatImplements(schema, type, interfaceName) {
|
|
return isAbstractType(type) && getConcreteTypes(schema, type).some(function (concreteType) {
|
|
return implementsInterface(concreteType, interfaceName);
|
|
});
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
|
|
|
|
function getConcreteTypes(schema, type) {
|
|
return schema.getPossibleTypes(assertAbstractType(type));
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
|
|
|
|
function getInterfaces(type) {
|
|
if (type instanceof GraphQLObjectType) {
|
|
return type.getInterfaces();
|
|
}
|
|
|
|
return [];
|
|
}
|
|
/**
|
|
* @public
|
|
*
|
|
* Determine if an AST node contains a fragment/operation definition.
|
|
*/
|
|
|
|
|
|
function isExecutableDefinitionAST(ast) {
|
|
return ast.kind === 'FragmentDefinition' || ast.kind === 'OperationDefinition';
|
|
}
|
|
/**
|
|
* @public
|
|
*
|
|
* Determine if an AST node contains a schema definition.
|
|
*/
|
|
|
|
|
|
function isSchemaDefinitionAST(ast) {
|
|
return ast.kind === 'SchemaDefinition' || ast.kind === 'ScalarTypeDefinition' || ast.kind === 'ObjectTypeDefinition' || ast.kind === 'InterfaceTypeDefinition' || ast.kind === 'UnionTypeDefinition' || ast.kind === 'EnumTypeDefinition' || ast.kind === 'InputObjectTypeDefinition' || ast.kind === 'DirectiveDefinition' || ast.kind === 'ScalarTypeExtension' || ast.kind === 'ObjectTypeExtension' || ast.kind === 'InterfaceTypeExtension' || ast.kind === 'UnionTypeExtension' || ast.kind === 'EnumTypeExtension' || ast.kind === 'InputObjectTypeExtension';
|
|
}
|
|
|
|
function assertTypeWithFields(type) {
|
|
!(type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) ? process.env.NODE_ENV !== "production" ? invariant(false, 'GraphQLSchemaUtils: Expected type `%s` to be an object or interface type.', type) : invariant(false) : void 0;
|
|
return type;
|
|
}
|
|
/**
|
|
* Helper for calling `typeFromAST()` with a clear warning when the type does
|
|
* not exist. This enables the pattern `assertXXXType(getTypeFromAST(...))`,
|
|
* emitting distinct errors for unknown types vs types of the wrong category.
|
|
*/
|
|
|
|
|
|
function getTypeFromAST(schema, ast) {
|
|
var type = typeFromAST(schema, ast);
|
|
!isType(type) ? process.env.NODE_ENV !== "production" ? invariant(false, 'GraphQLSchemaUtils: Unknown type `%s`.', print(ast)) : invariant(false) : void 0;
|
|
return type;
|
|
}
|
|
|
|
module.exports = {
|
|
assertTypeWithFields: assertTypeWithFields,
|
|
canHaveSelections: canHaveSelections,
|
|
getNullableType: getNullableType,
|
|
getRawType: getRawType,
|
|
getSingularType: getSingularType,
|
|
getTypeFromAST: getTypeFromAST,
|
|
hasID: hasID,
|
|
implementsInterface: implementsInterface,
|
|
isAbstractType: isAbstractType,
|
|
isUnionType: isUnionType,
|
|
isExecutableDefinitionAST: isExecutableDefinitionAST,
|
|
isSchemaDefinitionAST: isSchemaDefinitionAST,
|
|
mayImplement: mayImplement
|
|
}; |