Implement interface and union type querying
This commit is contained in:
parent
59be67391d
commit
d96470a62a
3 changed files with 63 additions and 17 deletions
|
@ -16,13 +16,6 @@ final Validator graphQlPostBody = new Validator({
|
|||
'variables': predicate((v) => v == null || v is Map),
|
||||
});
|
||||
|
||||
Map<String, dynamic> _foldToStringDynamic(Map map) {
|
||||
return map == null
|
||||
? null
|
||||
: map.keys.fold<Map<String, dynamic>>(
|
||||
<String, dynamic>{}, (out, k) => out..[k.toString()] = map[k]);
|
||||
}
|
||||
|
||||
RequestHandler graphQLHttp(GraphQL graphQl) {
|
||||
return (req, res) async {
|
||||
try {
|
||||
|
@ -41,7 +34,7 @@ RequestHandler graphQLHttp(GraphQL graphQl) {
|
|||
text,
|
||||
sourceUrl: 'input',
|
||||
operationName: operationName,
|
||||
variableValues: _foldToStringDynamic(variables),
|
||||
variableValues: foldToStringDynamic(variables),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,10 +13,12 @@ class GraphQLObjectType
|
|||
final List<GraphQLObjectType> _possibleTypes = [];
|
||||
|
||||
/// A list of other types that this object type is known to implement.
|
||||
List<GraphQLObjectType> get interfaces => new List<GraphQLObjectType>.unmodifiable(_interfaces);
|
||||
List<GraphQLObjectType> get interfaces =>
|
||||
new List<GraphQLObjectType>.unmodifiable(_interfaces);
|
||||
|
||||
/// A list of other types that implement this interface.
|
||||
List<GraphQLObjectType> get possibleTypes => new List<GraphQLObjectType>.unmodifiable(_possibleTypes);
|
||||
List<GraphQLObjectType> get possibleTypes =>
|
||||
new List<GraphQLObjectType>.unmodifiable(_possibleTypes);
|
||||
|
||||
GraphQLObjectType(this.name, this.description, {this.isInterface: false});
|
||||
|
||||
|
@ -88,6 +90,18 @@ class GraphQLObjectType
|
|||
return out..[k.toString()] = field.deserialize(value[k]);
|
||||
});
|
||||
}
|
||||
|
||||
bool isImplementationOf(GraphQLObjectType type) {
|
||||
if (type == this) {
|
||||
return true;
|
||||
} else if (interfaces.contains(type)) {
|
||||
return true;
|
||||
} else if (interfaces.isNotEmpty) {
|
||||
return interfaces.any((t) => t.isImplementationOf(type));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> _foldToStringDynamic(Map map) {
|
||||
|
|
|
@ -5,6 +5,13 @@ import 'package:graphql_schema/graphql_schema.dart';
|
|||
|
||||
import 'introspection.dart';
|
||||
|
||||
Map<String, dynamic> foldToStringDynamic(Map map) {
|
||||
return map == null
|
||||
? null
|
||||
: map.keys.fold<Map<String, dynamic>>(
|
||||
<String, dynamic>{}, (out, k) => out..[k.toString()] = map[k]);
|
||||
}
|
||||
|
||||
class GraphQL {
|
||||
final List<GraphQLType> customTypes = [];
|
||||
GraphQLSchema _schema;
|
||||
|
@ -335,17 +342,48 @@ class GraphQL {
|
|||
}
|
||||
}
|
||||
|
||||
if (fieldType is GraphQLObjectType) {
|
||||
var objectType = fieldType;
|
||||
if (fieldType is GraphQLObjectType || fieldType is GraphQLUnionType) {
|
||||
GraphQLObjectType objectType;
|
||||
|
||||
if (fieldType is GraphQLObjectType && !fieldType.isInterface) {
|
||||
objectType = fieldType;
|
||||
} else {
|
||||
objectType = resolveAbstractType(fieldType, result);
|
||||
}
|
||||
|
||||
var subSelectionSet = mergeSelectionSets(fields);
|
||||
return await executeSelectionSet(
|
||||
document, subSelectionSet, objectType, result, variableValues);
|
||||
}
|
||||
|
||||
// TODO: Interface/union type
|
||||
throw new UnsupportedError('Unsupported type: $fieldType');
|
||||
}
|
||||
|
||||
GraphQLObjectType resolveAbstractType(GraphQLType type, result) {
|
||||
List<GraphQLObjectType> possibleTypes;
|
||||
|
||||
if (type is GraphQLObjectType) {
|
||||
possibleTypes = type.possibleTypes;
|
||||
} else if (type is GraphQLUnionType) {
|
||||
possibleTypes = type.possibleTypes;
|
||||
} else {
|
||||
throw new ArgumentError();
|
||||
}
|
||||
|
||||
for (var t in possibleTypes) {
|
||||
try {
|
||||
var validation =
|
||||
t.validate('@root', foldToStringDynamic(result as Map));
|
||||
|
||||
if (validation.successful) {
|
||||
return t;
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
throw new StateError('Cannot convert value $result to type $type.');
|
||||
}
|
||||
|
||||
SelectionSetContext mergeSelectionSets(List<SelectionContext> fields) {
|
||||
var selections = <SelectionContext>[];
|
||||
|
||||
|
@ -451,13 +489,14 @@ class GraphQL {
|
|||
bool doesFragmentTypeApply(
|
||||
GraphQLObjectType objectType, TypeConditionContext fragmentType) {
|
||||
var type = convertType(new TypeContext(fragmentType.typeName, null));
|
||||
// TODO: Handle interface type, union?
|
||||
|
||||
if (type is GraphQLObjectType) {
|
||||
if (type is GraphQLObjectType && !type.isInterface) {
|
||||
for (var field in type.fields)
|
||||
if (!objectType.fields.any((f) => f.name == field.name)) return false;
|
||||
|
||||
return true;
|
||||
} else if (type is GraphQLObjectType && type.isInterface) {
|
||||
return objectType.isImplementationOf(type);
|
||||
} else if (type is GraphQLUnionType) {
|
||||
return type.possibleTypes.any((t) => objectType.isImplementationOf(t));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue