Union type introspection fixed

This commit is contained in:
Tobe O 2018-08-03 20:57:38 -04:00
parent 61ee37b4d9
commit 59be67391d
3 changed files with 64 additions and 40 deletions

View file

@ -1,22 +1,25 @@
part of graphql_schema.src.schema; part of graphql_schema.src.schema;
class GraphQLUnionType<Value, Serialized> extends GraphQLType<Value, Serialized> class GraphQLUnionType
with _NonNullableMixin<Value, Serialized> { extends GraphQLType<Map<String, dynamic>, Map<String, dynamic>>
final List<GraphQLType<Value, Serialized>> possibleTypes; with _NonNullableMixin<Map<String, dynamic>, Map<String, dynamic>> {
final String description; final String name;
final List<GraphQLObjectType> possibleTypes = [];
GraphQLUnionType(this.possibleTypes, {this.description}) { GraphQLUnionType(
assert(possibleTypes.every((t) => t is GraphQLUnionType), this.name,
'The member types of a Union type must all be Object base types; Scalar, Interface and Union types may not be member types of a Union. Similarly, wrapping types may not be member types of a Union'); Iterable<GraphQLObjectType> possibleTypes,
) {
assert(possibleTypes.isNotEmpty, assert(possibleTypes.isNotEmpty,
'A Union type must define one or more member types'); 'A Union type must define one or more member types.');
this.possibleTypes.addAll(possibleTypes.toSet());
} }
@override @override
String get name => possibleTypes.map((t) => t.name).join(' | '); String get description => possibleTypes.map((t) => t.name).join(' | ');
@override @override
Serialized serialize(Value value) { Map<String, dynamic> serialize(Map<String, dynamic> value) {
for (var type in possibleTypes) { for (var type in possibleTypes) {
try { try {
return type.serialize(value); return type.serialize(value);
@ -27,7 +30,7 @@ class GraphQLUnionType<Value, Serialized> extends GraphQLType<Value, Serialized>
} }
@override @override
Value deserialize(Serialized serialized) { Map<String, dynamic> deserialize(Map<String, dynamic> serialized) {
for (var type in possibleTypes) { for (var type in possibleTypes) {
try { try {
return type.deserialize(serialized); return type.deserialize(serialized);
@ -38,7 +41,8 @@ class GraphQLUnionType<Value, Serialized> extends GraphQLType<Value, Serialized>
} }
@override @override
ValidationResult<Serialized> validate(String key, Serialized input) { ValidationResult<Map<String, dynamic>> validate(
String key, Map<String, dynamic> input) {
List<String> errors = []; List<String> errors = [];
for (var type in possibleTypes) { for (var type in possibleTypes) {
@ -51,6 +55,6 @@ class GraphQLUnionType<Value, Serialized> extends GraphQLType<Value, Serialized>
} }
} }
return new ValidationResult._failure(errors); return new ValidationResult<Map<String, dynamic>>._failure(errors);
} }
} }

View file

@ -6,22 +6,31 @@ import 'package:graphql_schema/graphql_schema.dart';
import 'introspection.dart'; import 'introspection.dart';
class GraphQL { class GraphQL {
final Map<String, GraphQLType> customTypes = {}; final List<GraphQLType> customTypes = [];
GraphQLSchema _schema; GraphQLSchema _schema;
GraphQL(GraphQLSchema schema, {bool introspect: true}) : _schema = schema { GraphQL(GraphQLSchema schema,
{bool introspect: true,
List<GraphQLType> customTypes = const <GraphQLType>[]})
: _schema = schema {
if (customTypes?.isNotEmpty == true) {
this.customTypes.addAll(customTypes);
}
if (introspect) { if (introspect) {
var allTypes = <GraphQLType>[]; var allTypes = <GraphQLType>[];
allTypes.addAll(this.customTypes);
_schema = reflectSchema(_schema, allTypes); _schema = reflectSchema(_schema, allTypes);
for (var type in allTypes) { for (var type in allTypes) {
customTypes[type.name] = type; if (!this.customTypes.contains(type)) {
this.customTypes.add(type);
}
} }
} }
if (_schema.query != null) customTypes[_schema.query.name] = _schema.query; if (_schema.query != null) this.customTypes.add(_schema.query);
if (_schema.mutation != null) if (_schema.mutation != null) this.customTypes.add(_schema.mutation);
customTypes[_schema.mutation.name] = _schema.mutation;
} }
GraphQLType convertType(TypeContext ctx) { GraphQLType convertType(TypeContext ctx) {
@ -43,11 +52,9 @@ class GraphQL {
case 'DateTime': case 'DateTime':
return graphQLDate; return graphQLDate;
default: default:
if (customTypes.containsKey(ctx.typeName.name)) return customTypes.firstWhere((t) => t.name == ctx.typeName.name,
return customTypes[ctx.typeName.name]; orElse: () => throw new ArgumentError(
throw new ArgumentError( 'Unknown GraphQL type: "${ctx.typeName.name}"'));
'Unknown GraphQL type: "${ctx.typeName.name}"');
break;
} }
} else { } else {
throw new ArgumentError('Invalid GraphQL type: "${ctx.span.text}"'); throw new ArgumentError('Invalid GraphQL type: "${ctx.span.text}"');
@ -435,7 +442,8 @@ class GraphQL {
var vname = vv.variable.name; var vname = vv.variable.name;
if (!variableValues.containsKey(vname)) if (!variableValues.containsKey(vname))
throw new GraphQLException.fromSourceSpan('Unknown variable: "$vname"', vv.span); throw new GraphQLException.fromSourceSpan(
'Unknown variable: "$vname"', vv.span);
return variableValues[vname]; return variableValues[vname];
} }

View file

@ -3,6 +3,16 @@ import 'package:graphql_schema/graphql_schema.dart';
// TODO: How to handle custom types??? // TODO: How to handle custom types???
GraphQLSchema reflectSchema(GraphQLSchema schema, List<GraphQLType> allTypes) { GraphQLSchema reflectSchema(GraphQLSchema schema, List<GraphQLType> allTypes) {
for (var type in allTypes.toList()) {
var custom = _fetchAllTypesFromType(type);
for (var t in custom) {
if (!allTypes.contains(t)) {
allTypes.add(t);
}
}
}
var objectTypes = fetchAllTypes(schema, allTypes); var objectTypes = fetchAllTypes(schema, allTypes);
var typeType = _reflectSchemaTypes(); var typeType = _reflectSchemaTypes();
var directiveType = _reflectDirectiveType(); var directiveType = _reflectDirectiveType();
@ -210,8 +220,7 @@ GraphQLObjectType _createTypeType() {
else if (t is GraphQLUnionType) else if (t is GraphQLUnionType)
return 'UNION'; return 'UNION';
else else
throw new UnsupportedError( throw new UnsupportedError('Cannot get the kind of $t.');
'Cannot get the kind of $t.');
}, },
), ),
field( field(
@ -395,25 +404,28 @@ GraphQLObjectType _reflectEnumValueType() {
); );
} }
List<GraphQLObjectType> fetchAllTypes( List<GraphQLType> fetchAllTypes(
GraphQLSchema schema, List<GraphQLType> allTypes) { GraphQLSchema schema, List<GraphQLType> allTypes) {
var typess = <GraphQLType>[]; var types = <GraphQLType>[];
typess.addAll(_fetchAllTypesFromObject(schema.query));
types.addAll(_fetchAllTypesFromObject(schema.query));
if (schema.mutation != null) { if (schema.mutation != null) {
typess.addAll(_fetchAllTypesFromObject(schema.mutation) types.addAll(_fetchAllTypesFromObject(schema.mutation)
.where((t) => t is GraphQLObjectType)); .where((t) => t is GraphQLObjectType));
} }
var types = <GraphQLObjectType>[]; return types;
for (var type in typess) { // var types = <GraphQLObjectType>[];
if (type is GraphQLObjectType) //
types.add(type); // for (var type in typess) {
else if (!allTypes.contains(type)) allTypes.add(type); // if (type is GraphQLObjectType)
} // types.add(type);
// else if (!allTypes.contains(type)) allTypes.add(type);
return types.toSet().toList(); // }
//
// return types.toSet().toList();
} }
List<GraphQLType> _fetchAllTypesFromObject(GraphQLObjectType objectType) { List<GraphQLType> _fetchAllTypesFromObject(GraphQLObjectType objectType) {
@ -449,7 +461,7 @@ Iterable<GraphQLType> _fetchAllTypesFromType(GraphQLType type) {
types.addAll(_fetchAllTypesFromObject(type)); types.addAll(_fetchAllTypesFromObject(type));
} else if (type is GraphQLEnumType) { } else if (type is GraphQLEnumType) {
types.add(type); types.add(type);
} else if ( type is GraphQLUnionType) { } else if (type is GraphQLUnionType) {
for (var t in type.possibleTypes) { for (var t in type.possibleTypes) {
types.addAll(_fetchAllTypesFromType(t)); types.addAll(_fetchAllTypesFromType(t));
} }