Pedantic fixes
This commit is contained in:
parent
cf4b96da42
commit
77eb28f49c
7 changed files with 84 additions and 72 deletions
|
@ -45,11 +45,13 @@ class GraphQL {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_schema.queryType != null) this.customTypes.add(_schema.queryType);
|
if (_schema.queryType != null) this.customTypes.add(_schema.queryType);
|
||||||
if (_schema.mutationType != null)
|
if (_schema.mutationType != null) {
|
||||||
this.customTypes.add(_schema.mutationType);
|
this.customTypes.add(_schema.mutationType);
|
||||||
if (_schema.subscriptionType != null)
|
}
|
||||||
|
if (_schema.subscriptionType != null) {
|
||||||
this.customTypes.add(_schema.subscriptionType);
|
this.customTypes.add(_schema.subscriptionType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GraphQLType convertType(TypeContext ctx) {
|
GraphQLType convertType(TypeContext ctx) {
|
||||||
if (ctx.listType != null) {
|
if (ctx.listType != null) {
|
||||||
|
@ -115,10 +117,10 @@ class GraphQL {
|
||||||
var operation = getOperation(document, operationName);
|
var operation = getOperation(document, operationName);
|
||||||
var coercedVariableValues = coerceVariableValues(
|
var coercedVariableValues = coerceVariableValues(
|
||||||
schema, operation, variableValues ?? <String, dynamic>{});
|
schema, operation, variableValues ?? <String, dynamic>{});
|
||||||
if (operation.isQuery)
|
if (operation.isQuery) {
|
||||||
return await executeQuery(document, operation, schema,
|
return await executeQuery(document, operation, schema,
|
||||||
coercedVariableValues, initialValue, globalVariables);
|
coercedVariableValues, initialValue, globalVariables);
|
||||||
else if (operation.isSubscription) {
|
} else if (operation.isSubscription) {
|
||||||
return await subscribe(document, operation, schema, coercedVariableValues,
|
return await subscribe(document, operation, schema, coercedVariableValues,
|
||||||
globalVariables, initialValue);
|
globalVariables, initialValue);
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,20 +131,17 @@ class GraphQL {
|
||||||
|
|
||||||
OperationDefinitionContext getOperation(
|
OperationDefinitionContext getOperation(
|
||||||
DocumentContext document, String operationName) {
|
DocumentContext document, String operationName) {
|
||||||
var ops =
|
var ops = document.definitions.whereType<OperationDefinitionContext>();
|
||||||
document.definitions.where((d) => d is OperationDefinitionContext);
|
|
||||||
|
|
||||||
if (operationName == null) {
|
if (operationName == null) {
|
||||||
return ops.length == 1
|
return ops.length == 1
|
||||||
? ops.first as OperationDefinitionContext
|
? ops.first
|
||||||
: throw GraphQLException.fromMessage(
|
: throw GraphQLException.fromMessage(
|
||||||
'This document does not define any operations.');
|
'This document does not define any operations.');
|
||||||
} else {
|
} else {
|
||||||
return ops.firstWhere(
|
return ops.firstWhere((d) => d.name == operationName,
|
||||||
(d) => (d as OperationDefinitionContext).name == operationName,
|
|
||||||
orElse: () => throw GraphQLException.fromMessage(
|
orElse: () => throw GraphQLException.fromMessage(
|
||||||
'Missing required operation "$operationName".'))
|
'Missing required operation "$operationName".'));
|
||||||
as OperationDefinitionContext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,15 +240,17 @@ class GraphQL {
|
||||||
initialValue) {
|
initialValue) {
|
||||||
var selectionSet = subscription.selectionSet;
|
var selectionSet = subscription.selectionSet;
|
||||||
var subscriptionType = schema.subscriptionType;
|
var subscriptionType = schema.subscriptionType;
|
||||||
if (subscriptionType == null)
|
if (subscriptionType == null) {
|
||||||
throw GraphQLException.fromSourceSpan(
|
throw GraphQLException.fromSourceSpan(
|
||||||
'The schema does not define a subscription type.', subscription.span);
|
'The schema does not define a subscription type.', subscription.span);
|
||||||
|
}
|
||||||
var groupedFieldSet =
|
var groupedFieldSet =
|
||||||
collectFields(document, subscriptionType, selectionSet, variableValues);
|
collectFields(document, subscriptionType, selectionSet, variableValues);
|
||||||
if (groupedFieldSet.length != 1)
|
if (groupedFieldSet.length != 1) {
|
||||||
throw GraphQLException.fromSourceSpan(
|
throw GraphQLException.fromSourceSpan(
|
||||||
'The grouped field set from this query must have exactly one entry.',
|
'The grouped field set from this query must have exactly one entry.',
|
||||||
selectionSet.span);
|
selectionSet.span);
|
||||||
|
}
|
||||||
var fields = groupedFieldSet.entries.first.value;
|
var fields = groupedFieldSet.entries.first.value;
|
||||||
var fieldName = fields.first.field.fieldName.alias?.name ??
|
var fieldName = fields.first.field.fieldName.alias?.name ??
|
||||||
fields.first.field.fieldName.name;
|
fields.first.field.fieldName.name;
|
||||||
|
@ -284,10 +285,10 @@ class GraphQL {
|
||||||
Map<String, dynamic> globalVariables) async {
|
Map<String, dynamic> globalVariables) async {
|
||||||
var selectionSet = subscription.selectionSet;
|
var selectionSet = subscription.selectionSet;
|
||||||
var subscriptionType = schema.subscriptionType;
|
var subscriptionType = schema.subscriptionType;
|
||||||
if (subscriptionType == null)
|
if (subscriptionType == null) {
|
||||||
throw GraphQLException.fromSourceSpan(
|
throw GraphQLException.fromSourceSpan(
|
||||||
'The schema does not define a subscription type.', subscription.span);
|
'The schema does not define a subscription type.', subscription.span);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
var data = await executeSelectionSet(document, selectionSet,
|
var data = await executeSelectionSet(document, selectionSet,
|
||||||
subscriptionType, initialValue, variableValues, globalVariables);
|
subscriptionType, initialValue, variableValues, globalVariables);
|
||||||
|
@ -309,11 +310,12 @@ class GraphQL {
|
||||||
});
|
});
|
||||||
var resolver = field.resolve;
|
var resolver = field.resolve;
|
||||||
var result = await resolver(rootValue, argumentValues);
|
var result = await resolver(rootValue, argumentValues);
|
||||||
if (result is Stream)
|
if (result is Stream) {
|
||||||
return result;
|
return result;
|
||||||
else
|
} else {
|
||||||
return Stream.fromIterable([result]);
|
return Stream.fromIterable([result]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> executeSelectionSet(
|
Future<Map<String, dynamic>> executeSelectionSet(
|
||||||
DocumentContext document,
|
DocumentContext document,
|
||||||
|
@ -348,8 +350,7 @@ class GraphQL {
|
||||||
objectValue,
|
objectValue,
|
||||||
fields,
|
fields,
|
||||||
fieldType,
|
fieldType,
|
||||||
Map<String, dynamic>.from(
|
Map<String, dynamic>.from(globalVariables ?? <String, dynamic>{})
|
||||||
globalVariables ?? <String, dynamic>{})
|
|
||||||
..addAll(variableValues),
|
..addAll(variableValues),
|
||||||
globalVariables);
|
globalVariables);
|
||||||
}
|
}
|
||||||
|
@ -490,9 +491,10 @@ class GraphQL {
|
||||||
if (objectValue is Map) {
|
if (objectValue is Map) {
|
||||||
return objectValue[fieldName] as T;
|
return objectValue[fieldName] as T;
|
||||||
} else if (field.resolve == null) {
|
} else if (field.resolve == null) {
|
||||||
if (defaultFieldResolver != null)
|
if (defaultFieldResolver != null) {
|
||||||
return await defaultFieldResolver(
|
return await defaultFieldResolver(
|
||||||
objectValue, fieldName, argumentValues);
|
objectValue, fieldName, argumentValues);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -601,17 +603,14 @@ class GraphQL {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
errors
|
errors.addAll(validation.errors.map((m) => GraphQLExceptionError(m)));
|
||||||
.addAll(validation.errors.map((m) => GraphQLExceptionError(m)));
|
|
||||||
} on GraphQLException catch (e) {
|
} on GraphQLException catch (e) {
|
||||||
errors.addAll(e.errors);
|
errors.addAll(e.errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errors.insert(
|
errors.insert(0,
|
||||||
0,
|
GraphQLExceptionError('Cannot convert value $result to type $type.'));
|
||||||
GraphQLExceptionError(
|
|
||||||
'Cannot convert value $result to type $type.'));
|
|
||||||
|
|
||||||
throw GraphQLException(errors);
|
throw GraphQLException(errors);
|
||||||
}
|
}
|
||||||
|
@ -640,10 +639,13 @@ class GraphQL {
|
||||||
visitedFragments ??= [];
|
visitedFragments ??= [];
|
||||||
|
|
||||||
for (var selection in selectionSet.selections) {
|
for (var selection in selectionSet.selections) {
|
||||||
if (getDirectiveValue('skip', 'if', selection, variableValues) == true)
|
if (getDirectiveValue('skip', 'if', selection, variableValues) == true) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (getDirectiveValue('include', 'if', selection, variableValues) ==
|
if (getDirectiveValue('include', 'if', selection, variableValues) ==
|
||||||
false) continue;
|
false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (selection.field != null) {
|
if (selection.field != null) {
|
||||||
var responseKey = selection.field.fieldName.alias?.alias ??
|
var responseKey = selection.field.fieldName.alias?.alias ??
|
||||||
|
@ -656,11 +658,9 @@ class GraphQL {
|
||||||
if (visitedFragments.contains(fragmentSpreadName)) continue;
|
if (visitedFragments.contains(fragmentSpreadName)) continue;
|
||||||
visitedFragments.add(fragmentSpreadName);
|
visitedFragments.add(fragmentSpreadName);
|
||||||
var fragment = document.definitions
|
var fragment = document.definitions
|
||||||
.where((d) => d is FragmentDefinitionContext)
|
.whereType<FragmentDefinitionContext>()
|
||||||
.firstWhere(
|
.firstWhere((f) => f.name == fragmentSpreadName,
|
||||||
(f) =>
|
orElse: () => null);
|
||||||
(f as FragmentDefinitionContext).name == fragmentSpreadName,
|
|
||||||
orElse: () => null) as FragmentDefinitionContext;
|
|
||||||
|
|
||||||
if (fragment == null) continue;
|
if (fragment == null) continue;
|
||||||
var fragmentType = fragment.typeCondition;
|
var fragmentType = fragment.typeCondition;
|
||||||
|
@ -712,9 +712,10 @@ class GraphQL {
|
||||||
if (vv.value != null) return vv.value.value;
|
if (vv.value != null) return vv.value.value;
|
||||||
|
|
||||||
var vname = vv.variable.name;
|
var vname = vv.variable.name;
|
||||||
if (!variableValues.containsKey(vname))
|
if (!variableValues.containsKey(vname)) {
|
||||||
throw GraphQLException.fromSourceSpan(
|
throw GraphQLException.fromSourceSpan(
|
||||||
'Unknown variable: "$vname"', vv.span);
|
'Unknown variable: "$vname"', vv.span);
|
||||||
|
}
|
||||||
|
|
||||||
return variableValues[vname];
|
return variableValues[vname];
|
||||||
}
|
}
|
||||||
|
@ -723,8 +724,9 @@ class GraphQL {
|
||||||
GraphQLObjectType objectType, TypeConditionContext fragmentType) {
|
GraphQLObjectType objectType, TypeConditionContext fragmentType) {
|
||||||
var type = convertType(TypeContext(fragmentType.typeName, null));
|
var type = convertType(TypeContext(fragmentType.typeName, null));
|
||||||
if (type is GraphQLObjectType && !type.isInterface) {
|
if (type is GraphQLObjectType && !type.isInterface) {
|
||||||
for (var field in type.fields)
|
for (var field in type.fields) {
|
||||||
if (!objectType.fields.any((f) => f.name == field.name)) return false;
|
if (!objectType.fields.any((f) => f.name == field.name)) return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (type is GraphQLObjectType && type.isInterface) {
|
} else if (type is GraphQLObjectType && type.isInterface) {
|
||||||
return objectType.isImplementationOf(type);
|
return objectType.isImplementationOf(type);
|
||||||
|
|
|
@ -108,9 +108,9 @@ GraphQLObjectType _reflectSchemaTypes() {
|
||||||
'ofType',
|
'ofType',
|
||||||
_reflectSchemaTypes(),
|
_reflectSchemaTypes(),
|
||||||
resolve: (type, _) {
|
resolve: (type, _) {
|
||||||
if (type is GraphQLListType)
|
if (type is GraphQLListType) {
|
||||||
return type.ofType;
|
return type.ofType;
|
||||||
else if (type is GraphQLNonNullableType) return type.ofType;
|
} else if (type is GraphQLNonNullableType) return type.ofType;
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -213,22 +213,23 @@ GraphQLObjectType _createTypeType() {
|
||||||
resolve: (type, _) {
|
resolve: (type, _) {
|
||||||
var t = type as GraphQLType;
|
var t = type as GraphQLType;
|
||||||
|
|
||||||
if (t is GraphQLEnumType)
|
if (t is GraphQLEnumType) {
|
||||||
return 'ENUM';
|
return 'ENUM';
|
||||||
else if (t is GraphQLScalarType)
|
} else if (t is GraphQLScalarType) {
|
||||||
return 'SCALAR';
|
return 'SCALAR';
|
||||||
else if (t is GraphQLInputObjectType)
|
} else if (t is GraphQLInputObjectType) {
|
||||||
return 'INPUT_OBJECT';
|
return 'INPUT_OBJECT';
|
||||||
else if (t is GraphQLObjectType)
|
} else if (t is GraphQLObjectType) {
|
||||||
return t.isInterface ? 'INTERFACE' : 'OBJECT';
|
return t.isInterface ? 'INTERFACE' : 'OBJECT';
|
||||||
else if (t is GraphQLListType)
|
} else if (t is GraphQLListType) {
|
||||||
return 'LIST';
|
return 'LIST';
|
||||||
else if (t is GraphQLNonNullableType)
|
} else if (t is GraphQLNonNullableType) {
|
||||||
return 'NON_NULL';
|
return 'NON_NULL';
|
||||||
else if (t is GraphQLUnionType)
|
} else if (t is GraphQLUnionType) {
|
||||||
return 'UNION';
|
return 'UNION';
|
||||||
else
|
} else {
|
||||||
throw UnsupportedError('Cannot get the kind of $t.');
|
throw UnsupportedError('Cannot get the kind of $t.');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
field(
|
field(
|
||||||
|
|
|
@ -7,11 +7,12 @@ import 'package:recase/recase.dart';
|
||||||
/// Uses `dart:mirrors` to read field names from items. If they are Maps, performs a regular lookup.
|
/// Uses `dart:mirrors` to read field names from items. If they are Maps, performs a regular lookup.
|
||||||
T mirrorsFieldResolver<T>(objectValue, String fieldName,
|
T mirrorsFieldResolver<T>(objectValue, String fieldName,
|
||||||
[Map<String, dynamic> objectValues]) {
|
[Map<String, dynamic> objectValues]) {
|
||||||
if (objectValue is Map)
|
if (objectValue is Map) {
|
||||||
return objectValue[fieldName] as T;
|
return objectValue[fieldName] as T;
|
||||||
else
|
} else {
|
||||||
return reflect(objectValue).getField(Symbol(fieldName)).reflectee as T;
|
return reflect(objectValue).getField(Symbol(fieldName)).reflectee as T;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reflects upon a given [type] and dynamically generates a [GraphQLType] that corresponds to it.
|
/// Reflects upon a given [type] and dynamically generates a [GraphQLType] that corresponds to it.
|
||||||
///
|
///
|
||||||
|
|
|
@ -18,11 +18,12 @@ abstract class Server {
|
||||||
if ((msg.type == OperationMessage.gqlConnectionInit) && !_init) {
|
if ((msg.type == OperationMessage.gqlConnectionInit) && !_init) {
|
||||||
try {
|
try {
|
||||||
Map connectionParams;
|
Map connectionParams;
|
||||||
if (msg.payload is Map)
|
if (msg.payload is Map) {
|
||||||
connectionParams = msg.payload as Map;
|
connectionParams = msg.payload as Map;
|
||||||
else if (msg.payload != null)
|
} else if (msg.payload != null) {
|
||||||
throw FormatException(
|
throw FormatException(
|
||||||
'${msg.type} payload must be a map (object).');
|
'${msg.type} payload must be a map (object).');
|
||||||
|
}
|
||||||
|
|
||||||
var connect = await onConnect(client, connectionParams);
|
var connect = await onConnect(client, connectionParams);
|
||||||
if (!connect) throw false;
|
if (!connect) throw false;
|
||||||
|
@ -39,33 +40,39 @@ abstract class Server {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e == false)
|
if (e == false) {
|
||||||
_reportError('The connection was rejected.');
|
_reportError('The connection was rejected.');
|
||||||
else
|
} else {
|
||||||
_reportError(e.toString());
|
_reportError(e.toString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (_init) {
|
} else if (_init) {
|
||||||
if (msg.type == OperationMessage.gqlStart) {
|
if (msg.type == OperationMessage.gqlStart) {
|
||||||
if (msg.id == null)
|
if (msg.id == null) {
|
||||||
throw FormatException('${msg.type} id is required.');
|
throw FormatException('${msg.type} id is required.');
|
||||||
if (msg.payload == null)
|
}
|
||||||
|
if (msg.payload == null) {
|
||||||
throw FormatException('${msg.type} payload is required.');
|
throw FormatException('${msg.type} payload is required.');
|
||||||
else if (msg.payload is! Map)
|
} else if (msg.payload is! Map) {
|
||||||
throw FormatException(
|
throw FormatException(
|
||||||
'${msg.type} payload must be a map (object).');
|
'${msg.type} payload must be a map (object).');
|
||||||
|
}
|
||||||
var payload = msg.payload as Map;
|
var payload = msg.payload as Map;
|
||||||
var query = payload['query'];
|
var query = payload['query'];
|
||||||
var variables = payload['variables'];
|
var variables = payload['variables'];
|
||||||
var operationName = payload['operationName'];
|
var operationName = payload['operationName'];
|
||||||
if (query == null || query is! String)
|
if (query == null || query is! String) {
|
||||||
throw FormatException(
|
throw FormatException(
|
||||||
'${msg.type} payload must contain a string named "query".');
|
'${msg.type} payload must contain a string named "query".');
|
||||||
if (variables != null && variables is! Map)
|
}
|
||||||
|
if (variables != null && variables is! Map) {
|
||||||
throw FormatException(
|
throw FormatException(
|
||||||
'${msg.type} payload\'s "variables" field must be a map (object).');
|
'${msg.type} payload\'s "variables" field must be a map (object).');
|
||||||
if (operationName != null && operationName is! String)
|
}
|
||||||
|
if (operationName != null && operationName is! String) {
|
||||||
throw FormatException(
|
throw FormatException(
|
||||||
'${msg.type} payload\'s "operationName" field must be a string.');
|
'${msg.type} payload\'s "operationName" field must be a string.');
|
||||||
|
}
|
||||||
var result = await onOperation(
|
var result = await onOperation(
|
||||||
msg.id,
|
msg.id,
|
||||||
query as String,
|
query as String,
|
||||||
|
|
|
@ -44,14 +44,15 @@ class OperationMessage {
|
||||||
var payload = map['payload'];
|
var payload = map['payload'];
|
||||||
var id = map['id'];
|
var id = map['id'];
|
||||||
|
|
||||||
if (type == null)
|
if (type == null) {
|
||||||
throw ArgumentError.notNull('type');
|
throw ArgumentError.notNull('type');
|
||||||
else if (type is! String)
|
} else if (type is! String) {
|
||||||
throw ArgumentError.value(type, 'type', 'must be a string');
|
throw ArgumentError.value(type, 'type', 'must be a string');
|
||||||
else if (id is num)
|
} else if (id is num) {
|
||||||
id = id.toString();
|
id = id.toString();
|
||||||
else if (id != null && id is! String)
|
} else if (id != null && id is! String) {
|
||||||
throw ArgumentError.value(id, 'id', 'must be a string or number');
|
throw ArgumentError.value(id, 'id', 'must be a string or number');
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: This is technically a violation of the spec.
|
// TODO: This is technically a violation of the spec.
|
||||||
// https://github.com/apollographql/subscriptions-transport-ws/issues/551
|
// https://github.com/apollographql/subscriptions-transport-ws/issues/551
|
||||||
|
|
Loading…
Reference in a new issue