From a43893bde994a1eedef46cb02580030c0fe41573 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Fri, 3 Aug 2018 19:43:00 -0400 Subject: [PATCH] Add interface type --- graphql_schema/lib/src/gen.dart | 21 ++++++++++++----- graphql_schema/lib/src/object_type.dart | 30 ++++++++++++++++++++----- graphql_server/lib/introspection.dart | 21 ++++++++++++----- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/graphql_schema/lib/src/gen.dart b/graphql_schema/lib/src/gen.dart index 91b79c04..9ddc3329 100644 --- a/graphql_schema/lib/src/gen.dart +++ b/graphql_schema/lib/src/gen.dart @@ -1,12 +1,21 @@ part of graphql_schema.src.schema; GraphQLObjectType objectType(String name, - {String description, - Iterable fields = const [], - Iterable interfaces = const []}) => - new GraphQLObjectType(name, description) - ..fields.addAll(fields ?? []) - ..interfaces.addAll(interfaces ?? []); + {String description, + bool isInterface: false, + Iterable fields = const [], + Iterable interfaces = const []}) { + var obj = new GraphQLObjectType(name, description, isInterface: isInterface) + ..fields.addAll(fields ?? []); + + if (interfaces?.isNotEmpty == true) { + for (var i in interfaces) { + obj.inheritFrom(i); + } + } + + return obj; +} GraphQLField field(String name, {Iterable> arguments: const [], diff --git a/graphql_schema/lib/src/object_type.dart b/graphql_schema/lib/src/object_type.dart index 33a0c571..bf8e114a 100644 --- a/graphql_schema/lib/src/object_type.dart +++ b/graphql_schema/lib/src/object_type.dart @@ -6,11 +6,27 @@ class GraphQLObjectType final String name; final String description; final List fields = []; + final bool isInterface; + + final List _interfaces = []; + + final List _possibleTypes = []; /// A list of other types that this object type is known to implement. - final List interfaces = []; + List get interfaces => new List.unmodifiable(_interfaces); - GraphQLObjectType(this.name, this.description); + /// A list of other types that implement this interface. + List get possibleTypes => new List.unmodifiable(_possibleTypes); + + GraphQLObjectType(this.name, this.description, {this.isInterface: false}); + + void inheritFrom(GraphQLObjectType other) { + if (!_interfaces.contains(other)) { + _interfaces.add(other); + other._possibleTypes.add(this); + other._interfaces.forEach(inheritFrom); + } + } @override ValidationResult> validate(String key, Map input) { @@ -23,7 +39,8 @@ class GraphQLObjectType for (var field in fields) { if (field.type is GraphQLNonNullableType) { if (!input.containsKey(field.name) || input[field.name] == null) { - errors.add('Field "${field.name}, of type ${field.type} cannot be null."'); + errors.add( + 'Field "${field.name}, of type ${field.type} cannot be null."'); } } } @@ -56,7 +73,8 @@ class GraphQLObjectType return value.keys.fold>({}, (out, k) { var field = fields.firstWhere((f) => f.name == k, orElse: () => null); if (field == null) - throw new UnsupportedError('Cannot serialize field "$k", which was not defined in the schema.'); + throw new UnsupportedError( + 'Cannot serialize field "$k", which was not defined in the schema.'); return out..[k.toString()] = field.serialize(value[k]); }); } @@ -76,5 +94,5 @@ Map _foldToStringDynamic(Map map) { return map == null ? null : map.keys.fold>( - {}, (out, k) => out..[k.toString()] = map[k]); -} \ No newline at end of file + {}, (out, k) => out..[k.toString()] = map[k]); +} diff --git a/graphql_server/lib/introspection.dart b/graphql_server/lib/introspection.dart index a4a6ede3..a2582b1d 100644 --- a/graphql_server/lib/introspection.dart +++ b/graphql_server/lib/introspection.dart @@ -120,8 +120,11 @@ GraphQLObjectType _reflectSchemaTypes() { 'possibleTypes', type: listType(_reflectSchemaTypes().nonNullable()), resolve: (type, _) { - // TODO: Interface and union types - return []; + if (type is GraphQLObjectType && type.isInterface) { + return type.possibleTypes; + } else { + return null; + } }, ), ); @@ -195,7 +198,7 @@ GraphQLObjectType _createTypeType() { if (t is GraphQLScalarType) return 'SCALAR'; else if (t is GraphQLObjectType) - return 'OBJECT'; + return t.isInterface ? 'INTERFACE' : 'OBJECT'; else if (t is GraphQLListType) return 'LIST'; else if (t is GraphQLNonNullableType) @@ -204,7 +207,7 @@ GraphQLObjectType _createTypeType() { return 'ENUM'; else throw new UnsupportedError( - 'Cannot get the kind of $t.'); // TODO: Interface + union + 'Cannot get the kind of $t.'); // TODO: union }, ), field( @@ -424,6 +427,14 @@ List _fetchAllTypesFromObject(GraphQLObjectType objectType) { } } + for (var type in objectType.interfaces) { + types.addAll(_fetchAllTypesFromObject(type)); + } + + for (var type in objectType.possibleTypes) { + types.addAll(_fetchAllTypesFromObject(type)); + } + return types; } @@ -440,6 +451,6 @@ Iterable _fetchAllTypesFromType(GraphQLType type) { types.add(type); } - // TODO: Interface, union + // TODO: union return types; }