diff --git a/.gitignore b/.gitignore index 4d2a4d6..65485b6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ pubspec.lock # Directory created by dartdoc # If you don't generate documentation locally you can remove this line. doc/api/ + +# GraphQL IDE completion +graphql.config.json \ No newline at end of file diff --git a/ROADMAP.md b/ROADMAP.md index eb383f1..042af6e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -17,14 +17,13 @@ GQL query you built and is handling reconciliation between the HTTP response and ## Roadmap - `QueryBuilder`: - [ ] Builder - - [ ] Fields - - [ ] Alias - - [ ] Arguments + - [x] Fields + - [x] Arguments - [ ] Aliases - - [ ] Fragments + - [x] Fragments - [ ] Variables - - [ ] Directives - - [ ] **Optionnal** Inline Fragments + - [x] Directives + - [x] **Optionnal** Inline Fragments - `VariableBuilder`: - [ ] Builder - `MutationBuilder`: @@ -33,6 +32,7 @@ GQL query you built and is handling reconciliation between the HTTP response and - [ ] Variables - `QueryReconcilier`: - [ ] Reconciler + - [ ] Reconcile Aliases - `Scalar Types`: - [ ] Implements default types - `GraphQLAnnotations` (used to define queries and mutations): @@ -40,9 +40,9 @@ GQL query you built and is handling reconciliation between the HTTP response and - [ ] Field directive - [ ] Field alias - `GraphQLClient`: - - [ ] Factory + - [x] Factory - [ ] GraphQL Response - [ ] **Optionnal** GraphQL dart classes generation from a GQL schema -- [ ] **Optionnal** Translate GQL queries from String to `graphql_client` DSL +- [x] **Optionnal** Translate GQL queries from String to `graphql_client` DSL [1]: http://facebook.github.io/graphql/ \ No newline at end of file diff --git a/example/github_declarations.dart b/example/github_declarations.dart index 500da12..363d4ef 100644 --- a/example/github_declarations.dart +++ b/example/github_declarations.dart @@ -4,11 +4,11 @@ import 'package:graphql_client/graphql_client.dart'; -class Query { +class GithubGraphQLSchema implements Schema { Viewer viewer; - Query({this.viewer}); - Query.fromJSON(Map data) : viewer = new Viewer.fromJSON(data['viewer']); + GithubGraphQLSchema.fromJSON(Map data) + : viewer = new Viewer.fromJSON(data['viewer']); @override String toString() { @@ -20,15 +20,12 @@ ${indentLines(viewer.toString(), 4)} } } -class Viewer { +class Viewer implements Schema { GraphQLString login; - @GraphQLArguments('size: 200') GraphQLString avatarUrl; GraphQLString bio; - @GraphQLArguments('last: 2') GraphQLConnection gists; - Viewer({this.login, this.avatarUrl, this.bio, this.gists}); Viewer.fromJSON(Map data) : login = new GraphQLString(data['login']), avatarUrl = new GraphQLString(data['avatarUrl']), @@ -47,11 +44,10 @@ ${indentLines(gists.toString(), 2)} } } -class Gist { +class Gist implements Schema { GraphQLString name; GraphQLString description; - Gist({this.name, this.description}); Gist.fromJSON(Map data) : name = new GraphQLString(data['name']), description = new GraphQLString(data['description']); diff --git a/example/graphql_client_example.dart b/example/graphql_client_example.dart index f994c15..5ebbd47 100644 --- a/example/graphql_client_example.dart +++ b/example/graphql_client_example.dart @@ -27,24 +27,34 @@ main() async { client: client, logger: logger, endPoint: endPoint, - ); - - Query builtQuery = new Query( - viewer: new Viewer( - avatarUrl: new GraphQLString(), - login: new GraphQLString(), - bio: new GraphQLString(), - gists: new GraphQLConnection( - nodes: new Gist( - name: new GraphQLString(), - description: new GraphQLString(), - ), - ), - ), - ); - - await graphQLClient.execute( - builtQuery, + )..loadSchema(GithubGraphQLSchema); + + //language=GraphQL + String gqlQuery = ''' + query { + viewer { + avatarUrl(size: 200) + login + bio @include(if: false) + gists(first: 5) { + nodes { + ...ShortGist + } + } + } + } + + fragment ShortGist on Gist { + name + description + } + '''; + + var res = await graphQLClient.execute( + gqlQuery, headers: {'Authorization': 'bearer $apiToken'}, ); + + print(res.viewer.avatarUrl.value); + print(res.viewer.gists.nodes.first.name.value); } diff --git a/lib/graphql_client.dart b/lib/graphql_client.dart index b66e63f..573c7d7 100644 --- a/lib/graphql_client.dart +++ b/lib/graphql_client.dart @@ -12,5 +12,5 @@ export 'utils.dart'; export 'annotations.dart'; export 'scalar_types.dart'; export 'connection.dart'; -export 'query_builder.dart'; export 'query_reconcilier.dart'; +export 'schema.dart'; diff --git a/lib/query_builder.dart b/lib/query_builder.dart index bd836d2..78a9bdc 100644 --- a/lib/query_builder.dart +++ b/lib/query_builder.dart @@ -5,6 +5,7 @@ /// Support for doing something awesome. /// /// More dartdocs go here. +@Deprecated('Not used anymore') library graphql_client.query_builder; export 'src/query_builder.dart'; diff --git a/lib/schema.dart b/lib/schema.dart new file mode 100644 index 0000000..eca42c8 --- /dev/null +++ b/lib/schema.dart @@ -0,0 +1,10 @@ +// Copyright Thomas Hourlier. All rights reserved. +// Use of this source code is governed by a MIT-style license +// that can be found in the LICENSE file. + +/// Support for doing something awesome. +/// +/// More dartdocs go here. +library graphql_client.schema; + +export 'src/schema.dart'; diff --git a/lib/src/client.dart b/lib/src/client.dart index c83a543..e8bc8f5 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -6,17 +6,19 @@ library graphql_client.src.client; import 'dart:async'; import 'dart:convert'; +import 'dart:mirrors'; import 'package:http/http.dart'; import 'package:logging/logging.dart'; -import 'query_builder.dart'; import 'query_reconcilier.dart'; +import 'schema.dart'; class GraphQLClient { Client client; String endPoint; Logger logger; + ClassMirror _schemaMirror; GraphQLClient({ this.client, @@ -24,21 +26,29 @@ class GraphQLClient { this.logger, }); - Future execute(T query, + void loadSchema(Type schemaClass) { + _schemaMirror = reflectClass(schemaClass); + } + + Future execute(String gqlQuery, {Map headers = const {}}) async { - String gqlQuery = queryBuilder(query); + if (_schemaMirror == null) { + throw new StateError("You must load a schema before executing a query"); + } logger.finest('Query: $gqlQuery'); - var response = await client.post(endPoint, - headers: headers, - body: JSON.encode( - {'query': gqlQuery}, - )); + var response = await client.post( + endPoint, + headers: headers, + body: JSON.encode( + {'query': gqlQuery}, + ), + ); logger.finest('Response: ${response.body}'); - T reconciliedQuery = reconcileResponse(query, response.body); + T reconciliedQuery = reconcileResponse(_schemaMirror, response.body); logger.finest('Result: \n$reconciliedQuery'); diff --git a/lib/src/query_builder.dart b/lib/src/query_builder.dart index 67d69e0..f450a67 100644 --- a/lib/src/query_builder.dart +++ b/lib/src/query_builder.dart @@ -9,6 +9,7 @@ import 'dart:mirrors'; import 'annotations.dart'; import 'connection.dart'; +@Deprecated('Not used anymore') String buildInstanceQuery(InstanceMirror instanceMirror) { ClassMirror classMirror = instanceMirror.type; var classDeclarations = classMirror.declarations; @@ -60,6 +61,7 @@ String buildInstanceQuery(InstanceMirror instanceMirror) { return '{ ${gqlQuery.trim()} }'; } +@Deprecated('Not used anymore') String queryBuilder(T query) { InstanceMirror queryInstanceMirror = reflect(query); String gqlQuery = buildInstanceQuery(queryInstanceMirror); diff --git a/lib/src/query_reconcilier.dart b/lib/src/query_reconcilier.dart index 87bb366..371f491 100644 --- a/lib/src/query_reconcilier.dart +++ b/lib/src/query_reconcilier.dart @@ -7,10 +7,9 @@ library graphql_client.src.query_reconcilier; import 'dart:mirrors'; import 'dart:convert'; -T reconcileResponse(T query, String response) { +T reconcileResponse(ClassMirror schemaMirror, String response) { Map jsonResponse = JSON.decode(response); - ClassMirror classMirror = reflect(query).type; - return classMirror + return schemaMirror .newInstance(const Symbol('fromJSON'), [jsonResponse['data']]).reflectee; } diff --git a/lib/src/schema.dart b/lib/src/schema.dart new file mode 100644 index 0000000..045d6b3 --- /dev/null +++ b/lib/src/schema.dart @@ -0,0 +1,9 @@ +// Copyright Thomas Hourlier. All rights reserved. +// Use of this source code is governed by a MIT-style license +// that can be found in the LICENSE file. + +library graphql_client.src.schema; + +abstract class Schema { + Schema.fromJSON(Map data); +}