diff --git a/angel_graphql/example/main.dart b/angel_graphql/example/main.dart index 76bc50ae..d9ed9dec 100644 --- a/angel_graphql/example/main.dart +++ b/angel_graphql/example/main.dart @@ -66,4 +66,6 @@ class Todo extends Model { Todo({this.text, this.completed, this.completionStatus}); } -enum CompletionStatus { complete, incomplete } +@GraphQLDocumentation(description: 'The completion status of a to-do item.') +enum CompletionStatus { + COMPLETE, INCOMPLETE } diff --git a/graphql_server/lib/introspection.dart b/graphql_server/lib/introspection.dart index d0cb48ae..1fe80751 100644 --- a/graphql_server/lib/introspection.dart +++ b/graphql_server/lib/introspection.dart @@ -3,7 +3,7 @@ import 'package:graphql_schema/graphql_schema.dart'; // TODO: How to handle custom types??? GraphQLSchema reflectSchema(GraphQLSchema schema, List allTypes) { - var objectTypes = fetchAllTypes(schema); + var objectTypes = fetchAllTypes(schema, allTypes); var typeType = _reflectSchemaTypes(); var directiveType = _reflectDirectiveType(); allTypes.addAll(objectTypes); @@ -46,6 +46,8 @@ GraphQLSchema reflectSchema(GraphQLSchema schema, List allTypes) { directiveType, typeType, schemaType, + _typeKindType, + _directiveLocationType, _reflectFields(), _reflectDirectiveType(), _reflectInputValueType(), @@ -66,7 +68,7 @@ GraphQLSchema reflectSchema(GraphQLSchema schema, List allTypes) { ], resolve: (_, args) { var name = args['name'] as String; - return objectTypes.firstWhere((t) => t.name == name, + return allTypes.firstWhere((t) => t.name == name, orElse: () => throw new GraphQLException.fromMessage( 'No type named "$name" exists.')); }, @@ -156,6 +158,18 @@ GraphQLObjectType _reflectSchemaTypes() { return _typeType; } +final GraphQLEnumType _typeKindType = + enumTypeFromStrings('__TypeKind', [ + 'SCALAR', + 'OBJECT', + 'INTERFACE', + 'UNION', + 'ENUM', + 'INPUT_OBJECT', + 'LIST', + 'NON_NULL' +]); + GraphQLObjectType _createTypeType() { var enumValueType = _reflectEnumValueType(); var fieldType = _reflectFields(); @@ -174,7 +188,7 @@ GraphQLObjectType _createTypeType() { ), field( 'kind', - type: graphQLString, + type: _typeKindType, resolve: (type, _) { var t = type as GraphQLType; @@ -186,6 +200,8 @@ GraphQLObjectType _createTypeType() { return 'LIST'; else if (t is GraphQLNonNullableType) return 'NON_NULL'; + else if (t is GraphQLEnumType) + return 'ENUM'; else throw new UnsupportedError( 'Cannot get the kind of $t.'); // TODO: Interface + union @@ -218,6 +234,16 @@ GraphQLObjectType _createTypeType() { defaultValue: false, ), ], + resolve: (obj, args) { + if (obj is GraphQLEnumType) { + return obj.values + .where( + (f) => !f.isDeprecated || args['includeDeprecated'] == true) + .toList(); + } else { + return null; + } + }, ), field( 'inputFields', @@ -292,6 +318,16 @@ GraphQLObjectType _reflectInputValueType() { GraphQLObjectType _directiveType; +final GraphQLEnumType _directiveLocationType = + enumTypeFromStrings('__DirectiveLocation', [ + 'QUERY', + 'MUTATION', + 'FIELD', + 'FRAGMENT_DEFINITION', + 'FRAGMENT_SPREAD', + 'INLINE_FRAGMENT' +]); + GraphQLObjectType _reflectDirectiveType() { var inputValueType = _reflectInputValueType(); @@ -309,15 +345,7 @@ GraphQLObjectType _reflectDirectiveType() { ), field( 'locations', - type: listType(enumTypeFromStrings('DirectiveLocation', [ - 'QUERY', - 'MUTATION', - 'FIELD', - 'FRAGMENT_DEFINITION', - 'FRAGMENT_SPREAD', - 'INLINE_FRAGMENT' - ]).nonNullable()) - .nonNullable(), + type: listType(_directiveLocationType.nonNullable()).nonNullable(), // TODO: Fetch directiveLocation resolve: (obj, _) => [], ), @@ -360,7 +388,8 @@ GraphQLObjectType _reflectEnumValueType() { ); } -List fetchAllTypes(GraphQLSchema schema) { +List fetchAllTypes( + GraphQLSchema schema, List allTypes) { var typess = []; typess.addAll(_fetchAllTypesFromObject(schema.query)); @@ -372,7 +401,9 @@ List fetchAllTypes(GraphQLSchema schema) { var types = []; for (var type in typess) { - if (type is GraphQLObjectType) types.add(type); + if (type is GraphQLObjectType) + types.add(type); + else if (!allTypes.contains(type)) allTypes.add(type); } return types.toSet().toList(); diff --git a/graphql_server/lib/mirrors.dart b/graphql_server/lib/mirrors.dart index 8f5bda33..54a9dc39 100644 --- a/graphql_server/lib/mirrors.dart +++ b/graphql_server/lib/mirrors.dart @@ -79,15 +79,19 @@ GraphQLEnumType enumTypeFromClassMirror(ClassMirror mirror) { var values = []; for (var name in mirror.staticMembers.keys) { - var methodMirror = mirror.staticMembers[name]; - values.add( - new GraphQLEnumValue( - MirrorSystem.getName(name), - mirror.getField(name).reflectee, - description: _getDescription(methodMirror.metadata), - deprecationReason: _getDeprecationReason(methodMirror.metadata), - ), - ); + if (name != #values) { + var methodMirror = mirror.staticMembers[name]; + values.add( + new GraphQLEnumValue( + MirrorSystem.getName(name), + mirror + .getField(name) + .reflectee, + description: _getDescription(methodMirror.metadata), + deprecationReason: _getDeprecationReason(methodMirror.metadata), + ), + ); + } } return new GraphQLEnumType(