No longer require name after operation type
This commit is contained in:
parent
0a1928cf26
commit
a2454be927
3 changed files with 70 additions and 57 deletions
|
@ -19,7 +19,7 @@ main() async {
|
|||
|
||||
var todoService = app.use('api/todos', new MapService()) as Service;
|
||||
|
||||
var api = objectType(
|
||||
var queryType = objectType(
|
||||
'Query',
|
||||
description: 'A simple API that manages your to-do list.',
|
||||
fields: [
|
||||
|
@ -39,7 +39,21 @@ main() async {
|
|||
],
|
||||
);
|
||||
|
||||
var schema = graphQLSchema(query: api);
|
||||
var mutationType = objectType(
|
||||
'Mutation',
|
||||
description: 'Modify the to-do list.',
|
||||
fields: [
|
||||
field(
|
||||
'create',
|
||||
type: graphQLString,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
var schema = graphQLSchema(
|
||||
query: queryType,
|
||||
mutation: mutationType,
|
||||
);
|
||||
|
||||
app.all('/graphql', graphQLHttp(new GraphQL(schema)));
|
||||
app.get('/graphiql', graphiql());
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_validate/server.dart';
|
||||
import 'package:dart2_constant/convert.dart';
|
||||
|
@ -13,12 +12,36 @@ final ContentType graphQlContentType =
|
|||
final Validator graphQlPostBody = new Validator({
|
||||
'query*': isNonEmptyString,
|
||||
'operation_name': isNonEmptyString,
|
||||
'variables': predicate((v) => v == null || v is Map),
|
||||
'variables': predicate((v) => v == null || v is String || v is Map),
|
||||
});
|
||||
|
||||
RequestHandler graphQLHttp(GraphQL graphQl) {
|
||||
return (req, res) async {
|
||||
executeMap(Map map) async {
|
||||
var text = req.body['query'] as String;
|
||||
var operationName = req.body['operation_name'] as String;
|
||||
var variables = req.body['variables'];
|
||||
|
||||
if (variables is String) {
|
||||
variables = json.decode(variables as String);
|
||||
}
|
||||
|
||||
return {
|
||||
'data': await graphQl.parseAndExecute(
|
||||
text,
|
||||
sourceUrl: 'input',
|
||||
operationName: operationName,
|
||||
variableValues: foldToStringDynamic(variables as Map),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
if (req.method == 'GET') {
|
||||
if (await validateQuery(graphQlPostBody)(req, res)) {
|
||||
return await executeMap(req.query);
|
||||
}
|
||||
} else if (req.method == 'POST') {
|
||||
if (req.headers.contentType?.mimeType == graphQlContentType.mimeType) {
|
||||
var text = utf8.decode(await req.lazyOriginalBuffer());
|
||||
return {
|
||||
|
@ -26,17 +49,10 @@ RequestHandler graphQLHttp(GraphQL graphQl) {
|
|||
};
|
||||
} else if (req.headers.contentType?.mimeType == 'application/json') {
|
||||
if (await validate(graphQlPostBody)(req, res)) {
|
||||
var text = req.body['query'] as String;
|
||||
var operationName = req.body['operation_name'] as String;
|
||||
var variables = req.body['variables'] as Map;
|
||||
return {
|
||||
'data': await graphQl.parseAndExecute(
|
||||
text,
|
||||
sourceUrl: 'input',
|
||||
operationName: operationName,
|
||||
variableValues: foldToStringDynamic(variables),
|
||||
),
|
||||
};
|
||||
return await executeMap(req.body);
|
||||
}
|
||||
} else {
|
||||
throw new AngelHttpException.badRequest();
|
||||
}
|
||||
} else {
|
||||
throw new AngelHttpException.badRequest();
|
||||
|
|
|
@ -56,8 +56,7 @@ class Parser {
|
|||
else {
|
||||
if (next(TokenType.MUTATION) || next(TokenType.QUERY)) {
|
||||
var TYPE = current;
|
||||
if (next(TokenType.NAME)) {
|
||||
var NAME = current;
|
||||
Token NAME = next(TokenType.NAME) ? current : null;
|
||||
var variables = parseVariableDefinitions();
|
||||
var dirs = parseDirectives();
|
||||
var selectionSet = parseSelectionSet();
|
||||
|
@ -67,12 +66,7 @@ class Parser {
|
|||
..directives.addAll(dirs);
|
||||
else
|
||||
throw new SyntaxError(
|
||||
'Expected selection set in fragment definition.',
|
||||
NAME.span);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected name after operation type "${TYPE.text}" in operation definition.',
|
||||
TYPE.span);
|
||||
'Expected selection set in fragment definition.', NAME.span);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
@ -142,11 +136,8 @@ class Parser {
|
|||
ELLIPSIS, ON, typeCondition, selectionSet)
|
||||
..directives.addAll(directives);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected selection set in inline fragment.',
|
||||
directives.isEmpty
|
||||
? typeCondition.span
|
||||
: directives.last.span);
|
||||
throw new SyntaxError('Expected selection set in inline fragment.',
|
||||
directives.isEmpty ? typeCondition.span : directives.last.span);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected type condition after "on" in inline fragment.',
|
||||
|
@ -174,8 +165,7 @@ class Parser {
|
|||
return new SelectionSetContext(LBRACE, current)
|
||||
..selections.addAll(selections);
|
||||
else
|
||||
throw new SyntaxError(
|
||||
'Expected "}" after selection set.',
|
||||
throw new SyntaxError('Expected "}" after selection set.',
|
||||
selections.isEmpty ? LBRACE.span : selections.last.span);
|
||||
} else
|
||||
return null;
|
||||
|
@ -287,11 +277,9 @@ class Parser {
|
|||
if (next(TokenType.RBRACKET)) {
|
||||
return new ListTypeContext(LBRACKET, type, current);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected "]" in list type.', type.span);
|
||||
throw new SyntaxError('Expected "]" in list type.', type.span);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected type after "[".', LBRACKET.span);
|
||||
throw new SyntaxError('Expected type after "[".', LBRACKET.span);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
@ -331,8 +319,7 @@ class Parser {
|
|||
return new DirectiveContext(
|
||||
ARROBA, NAME, null, LPAREN, current, arg, null);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected \')\'', arg.valueOrVariable.span);
|
||||
throw new SyntaxError('Expected \')\'', arg.valueOrVariable.span);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected argument in directive.', LPAREN.span);
|
||||
|
@ -340,8 +327,7 @@ class Parser {
|
|||
return new DirectiveContext(
|
||||
ARROBA, NAME, null, null, null, null, null);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected name for directive.', ARROBA.span);
|
||||
throw new SyntaxError('Expected name for directive.', ARROBA.span);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
@ -363,8 +349,7 @@ class Parser {
|
|||
if (next(TokenType.RPAREN))
|
||||
return out;
|
||||
else
|
||||
throw new SyntaxError(
|
||||
'Expected ")" in argument list.', LPAREN.span);
|
||||
throw new SyntaxError('Expected ")" in argument list.', LPAREN.span);
|
||||
} else
|
||||
return [];
|
||||
}
|
||||
|
@ -420,8 +405,7 @@ class Parser {
|
|||
if (value != null) {
|
||||
return new DefaultValueContext(EQUALS, value);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Expected value after "=" sign.', EQUALS.span);
|
||||
throw new SyntaxError('Expected value after "=" sign.', EQUALS.span);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
@ -474,8 +458,7 @@ class Parser {
|
|||
if (next(TokenType.RBRACKET)) {
|
||||
return new ArrayValueContext(LBRACKET, current)..values.addAll(values);
|
||||
} else
|
||||
throw new SyntaxError(
|
||||
'Unterminated array literal.', LBRACKET.span);
|
||||
throw new SyntaxError('Unterminated array literal.', LBRACKET.span);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue