Union type introspection fixed
This commit is contained in:
parent
61ee37b4d9
commit
59be67391d
3 changed files with 64 additions and 40 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue