Finished coerceArgumentValues

This commit is contained in:
Tobe O 2018-08-02 09:50:31 -04:00
parent cd4a2233de
commit 4f91c0b6a8
4 changed files with 57 additions and 16 deletions

View file

@ -4,5 +4,10 @@ class GraphQLFieldArgument<Value, Serialized> {
final String name; final String name;
final GraphQLType<Value, Serialized> type; final GraphQLType<Value, Serialized> type;
final Value defaultValue; final Value defaultValue;
GraphQLFieldArgument(this.name, this.type, {this.defaultValue});
/// If [defaultValue] is `null`, and `null` is a valid value for this argument, set this to `true`.
final bool defaultsToNull;
GraphQLFieldArgument(this.name, this.type,
{this.defaultValue, this.defaultsToNull: false});
} }

View file

@ -4,12 +4,17 @@ typedef FutureOr<Value> GraphQLFieldResolver<Value, Serialized>(
Serialized serialized); Serialized serialized);
class GraphQLField<Value, Serialized> { class GraphQLField<Value, Serialized> {
final List<GraphQLFieldArgument> arguments = <GraphQLFieldArgument>[];
final String name; final String name;
final GraphQLFieldArgument argument;
final GraphQLFieldResolver<Value, Serialized> resolve; final GraphQLFieldResolver<Value, Serialized> resolve;
final GraphQLType<Value, Serialized> type; final GraphQLType<Value, Serialized> type;
GraphQLField(this.name, {this.argument, this.resolve, this.type}); GraphQLField(this.name,
{Iterable<GraphQLFieldArgument> arguments: const <GraphQLFieldArgument>[],
this.resolve,
this.type}) {
this.arguments.addAll(arguments ?? <GraphQLFieldArgument>[]);
}
FutureOr<Serialized> serialize(Value value) { FutureOr<Serialized> serialize(Value value) {
return type.serialize(value); return type.serialize(value);

View file

@ -5,6 +5,8 @@ abstract class GraphQLType<Value, Serialized> {
Value deserialize(Serialized serialized); Value deserialize(Serialized serialized);
ValidationResult<Serialized> validate(String key, Serialized input); ValidationResult<Serialized> validate(String key, Serialized input);
GraphQLType<Value, Serialized> nonNullable(); GraphQLType<Value, Serialized> nonNullable();
bool get isNullable => false;
} }
/// Shorthand to create a [GraphQLListType]. /// Shorthand to create a [GraphQLListType].
@ -64,6 +66,9 @@ class _GraphQLNonNullableType<Value, Serialized>
final GraphQLType<Value, Serialized> type; final GraphQLType<Value, Serialized> type;
_GraphQLNonNullableType._(this.type); _GraphQLNonNullableType._(this.type);
@override
bool get isNullable => true;
@override @override
GraphQLType<Value, Serialized> nonNullable() { GraphQLType<Value, Serialized> nonNullable() {
throw new UnsupportedError( throw new UnsupportedError(

View file

@ -33,8 +33,7 @@ class GraphQL {
if (customTypes.containsKey(ctx.typeName.name)) if (customTypes.containsKey(ctx.typeName.name))
return customTypes[ctx.typeName.name]; return customTypes[ctx.typeName.name];
throw new ArgumentError( throw new ArgumentError(
'Unknown GraphQL type: "${ctx.typeName.name}"\n${ctx.span 'Unknown GraphQL type: "${ctx.typeName.name}"\n${ctx.span.highlight()}');
.highlight()}');
break; break;
} }
} else { } else {
@ -48,7 +47,7 @@ class GraphQL {
{Map<String, dynamic> variableValues: const {}, initialValue}) { {Map<String, dynamic> variableValues: const {}, initialValue}) {
var operation = getOperation(document, operationName); var operation = getOperation(document, operationName);
var coercedVariableValues = var coercedVariableValues =
coerceVariableValues(schema, operation, variableValues ?? {}); coerceVariableValues(schema, operation, variableValues ?? {});
if (operation.isQuery) if (operation.isQuery)
return executeQuery( return executeQuery(
document, operation, schema, coercedVariableValues, initialValue); document, operation, schema, coercedVariableValues, initialValue);
@ -65,7 +64,7 @@ class GraphQL {
return ops.length == 1 return ops.length == 1
? ops.first ? ops.first
: throw new GraphQLException( : throw new GraphQLException(
'Missing required operation "$operationName".'); 'Missing required operation "$operationName".');
} else { } else {
return ops.firstWhere((d) => d.name == operationName, return ops.firstWhere((d) => d.name == operationName,
orElse: () => throw new GraphQLException( orElse: () => throw new GraphQLException(
@ -128,7 +127,7 @@ class GraphQL {
objectValue, objectValue,
Map<String, dynamic> variableValues) { Map<String, dynamic> variableValues) {
var groupedFieldSet = var groupedFieldSet =
collectFields(document, objectType, selectionSet, variableValues); collectFields(document, objectType, selectionSet, variableValues);
var resultMap = <String, dynamic>{}; var resultMap = <String, dynamic>{};
for (var responseKey in groupedFieldSet.keys) { for (var responseKey in groupedFieldSet.keys) {
@ -156,7 +155,7 @@ class GraphQL {
Map<String, dynamic> variableValues) { Map<String, dynamic> variableValues) {
var field = fields[0]; var field = fields[0];
var argumentValues = var argumentValues =
coerceArgumentValues(objectType, field, variableValues); coerceArgumentValues(objectType, field, variableValues);
var resolvedValue = resolveFieldValue( var resolvedValue = resolveFieldValue(
objectType, objectValue, field.field.fieldName.name, argumentValues); objectType, objectValue, field.field.fieldName.name, argumentValues);
return completeValue(fieldType, fields, resolvedValue, variableValues); return completeValue(fieldType, fields, resolvedValue, variableValues);
@ -168,9 +167,36 @@ class GraphQL {
var argumentValues = field.field.arguments; var argumentValues = field.field.arguments;
var fieldName = field.field.fieldName.name; var fieldName = field.field.fieldName.name;
var desiredField = objectType.fields.firstWhere((f) => f.name == fieldName); var desiredField = objectType.fields.firstWhere((f) => f.name == fieldName);
var argumentDefinitions = desiredField.arguments;
// TODO: Multiple arguments? for (var argumentDefinition in argumentDefinitions) {
var argumentDefinitions = desiredField.argument; var argumentName = argumentDefinition.name;
var argumentType = argumentDefinition.type;
var defaultValue = argumentDefinition.defaultValue;
var value = argumentValues.firstWhere((a) => a.name == argumentName,
orElse: () => null);
if (value != null) {
var variableName = value.name;
var variableValue = variableValues[variableName];
if (variableValues.containsKey(variableName)) {
coercedValues[argumentName] = variableValue;
} else if (defaultValue != null || argumentDefinition.defaultsToNull) {
coercedValues[argumentName] = defaultValue;
} else if (!argumentType.isNullable) {
throw new GraphQLException(
'Missing value for argument "$argumentName".');
}
} else {
if (defaultValue != null || argumentDefinition.defaultsToNull) {
coercedValues[argumentName] = defaultValue;
} else if (!argumentType.isNullable) {
throw new GraphQLException(
'Missing value for argument "$argumentName".');
}
}
}
return coercedValues; return coercedValues;
} }
@ -192,7 +218,7 @@ class GraphQL {
if (selection.field != null) { if (selection.field != null) {
var responseKey = selection.field.fieldName.name; var responseKey = selection.field.fieldName.name;
var groupForResponseKey = var groupForResponseKey =
groupedFields.putIfAbsent(responseKey, () => []); groupedFields.putIfAbsent(responseKey, () => []);
groupForResponseKey.add(selection); groupForResponseKey.add(selection);
} else if (selection.fragmentSpread != null) { } else if (selection.fragmentSpread != null) {
var fragmentSpreadName = selection.fragmentSpread.name; var fragmentSpreadName = selection.fragmentSpread.name;
@ -201,7 +227,7 @@ class GraphQL {
var fragment = document.definitions var fragment = document.definitions
.whereType<FragmentDefinitionContext>() .whereType<FragmentDefinitionContext>()
.firstWhere((f) => f.name == fragmentSpreadName, .firstWhere((f) => f.name == fragmentSpreadName,
orElse: () => null); orElse: () => null);
if (fragment == null) continue; if (fragment == null) continue;
var fragmentType = fragment.typeCondition; var fragmentType = fragment.typeCondition;
@ -213,7 +239,7 @@ class GraphQL {
for (var responseKey in fragmentGroupFieldSet.keys) { for (var responseKey in fragmentGroupFieldSet.keys) {
var fragmentGroup = fragmentGroupFieldSet[responseKey]; var fragmentGroup = fragmentGroupFieldSet[responseKey];
var groupForResponseKey = var groupForResponseKey =
groupedFields.putIfAbsent(responseKey, () => []); groupedFields.putIfAbsent(responseKey, () => []);
groupForResponseKey.addAll(fragmentGroup); groupForResponseKey.addAll(fragmentGroup);
} }
} else if (selection.inlineFragment != null) { } else if (selection.inlineFragment != null) {
@ -227,7 +253,7 @@ class GraphQL {
for (var responseKey in fragmentGroupFieldSet.keys) { for (var responseKey in fragmentGroupFieldSet.keys) {
var fragmentGroup = fragmentGroupFieldSet[responseKey]; var fragmentGroup = fragmentGroupFieldSet[responseKey];
var groupForResponseKey = var groupForResponseKey =
groupedFields.putIfAbsent(responseKey, () => []); groupedFields.putIfAbsent(responseKey, () => []);
groupForResponseKey.addAll(fragmentGroup); groupForResponseKey.addAll(fragmentGroup);
} }
} }