Code Monkey home page Code Monkey logo

graphql-flutter's Introduction

GraphQL Flutter

A collection of packages to work with graphql server in dart and flutter.

GitHub Workflow Status (branch) Pub Popularity Discord

Introduction

GraphQL brings many benefits, both to the client: devices will need fewer requests, and therefore reduce data usage. And to the programmer: requests are arguable, they have the same structure as the request.

This project combines the benefits of GraphQL with the benefits of Streams in Dart to deliver a high-performance client.

The project took inspiration from the Apollo GraphQL client, great work guys!

Packages

This is a Monorepo which contains the following packages:

Crate Description Version
graphql Client implementation to interact with any graphql server Pub Version (including pre-releases)
graphql_flutter Flutter Widgets wrapper around graphql API Pub Version (including pre-releases)

Utils Tools

Around graphql_flutter are builds awesome tools like:

  1. graphql_flutter_bloc
  2. graphql_codegen
  3. graphql-cache-inspector

Features

✅   Queries, Mutations, and Subscriptions
✅   Query polling and rebroadcasting
✅   In memory and persistent caching
✅   GraphQL Upload
✅   Optimistic results
✅   Modularity
✅   Client-state management
⚠️   Automatic Persisted Queries (out of service)

Contributing

Please see our Hacking guide

Contributors

This package was originally created and published by the engineers at Zino App BV. Since then the community has helped to make it even more useful for even more developers.

This project follows the all-contributors specification. Contributions of any kind are welcome!

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

Articles and Videos

External guides, tutorials, and other resources from the GraphQL Flutter community

graphql-flutter's People

Contributors

aarsham avatar budde377 avatar cal-pratt avatar camuthig avatar dbarcinas avatar dehypnosis avatar eugenepisotsky avatar eusdima avatar hofmannz avatar kamilkarp avatar klavs avatar kulture-rob-snider avatar lordgreg avatar lucasavila00 avatar mainawycliffe avatar micimize avatar mo-ah-dawood avatar mschmack avatar ndelanou avatar ol88 avatar othorin avatar semantic-release-bot avatar szantogab avatar toonvanstrijpwavy avatar truongsinh avatar vasilich6107 avatar vemarav avatar vincenzopalazzo avatar waitak avatar yunyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-flutter's Issues

Multiple Queries in single Widget ???

First of all congrats for superb work, I am originally a react native + graphql + apollo developer and developing apps on that. when I found this package I moved to Flutter as it gives high performance in fast development, but, in apollo

I was able to get multiple results from different queries like -

export default compose(
  graphql(GET_AUTH_USERS_QUERY, { name: "getAuthUser" }),
  graphql(GET_AUTH_USER_SUBSCRIPTIONS_QUERY, {
    name: "getChannelSubscriptionsQuery"
  }),
  graphql(GET_AUTH_USERS_POST_QUERY, {
    name: "getAuthUsersPostQuery"
  })
)(HomeScreen);

// here I am getting authUser detail, his channels subscriptions, his posts etc

How can I request for multiple queries ???

Can i do something like this ???

Query(
        [queries.getUser, queries.getUserSubsriptions], // in array ???
        builder: ({bool loading, var data, String error}) {
          if (loading) {
            return Center(
              child: CircularProgressIndicator(),
            );
          } 
       
          if(data){
              return Text("data[0]")
          }
       }
)

Question on GraphQLConsumer

I am new to flutter and want to use GraphQL and your package.
When I try to call GraphqlConsumer it seems that the builder never gets called.

Here is the example. Can someone help me with what I am doing wrong.

main.dart
`
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import './queries/query_storeship_orders.dart' as queries;

void main() {
runApp(TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
ValueNotifier client = ValueNotifier(
Client(
endPoint: 'http://172.16.18.12:8080/graphql',
cache: InMemoryCache()
),
);

return GraphqlProvider(
  client: client,
  child: CacheProvider(
    child: MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
            centerTitle: true,
            title: Text('Ship IT 1'),
          ),
          body: TabBarView(
            children: [
              ListView.builder(
                padding: new EdgeInsets.all(8.0),
                itemExtent: 20.0,
                itemBuilder: (BuildContext context, int index) {
                  return new Text('entry $index');
                },
              ),
              Icon(Icons.directions_transit),
               RaisedButton(
                child: const Text('Connect with Twitter'),
                color: Theme.of(context).accentColor,
                elevation: 4.0,
                splashColor: Colors.blueGrey,
                onPressed: ()  {
                  // Perform some action
                  //Client client = GraphqlProvider.of(context).value;
                  //var hello = client.query(query: queries.query_storeship_orders);

                  return new GraphqlConsumer(
                    builder: (Client client) {
                      var result = client.query(query: queries.query_storeship_orders);
                      return new Container(
                        child: new Text('Hello widget'),
                      );
                    }
                  );

                },
              ),
              //Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    ),
  ),
);

}
}
`

query_storeship_orders.dart

String query_storeship_orders = """ query{ storeOrderStatus { id, storeno, storename, cust_name, cust_email, order_number, order_status } } """ .replaceAll('\n', ' ');

Subscription support

Is there any short term plan for subscription support yet? If yes how soon else a good direction to start off in implementing the support would be awesome. I am not strong in dart yet, but I can take a plunge. Thank you guys. Graphql support for flutter was a big plus for me making my decision to use flutter

Json parse response error

Greetings,

Performing a simple query to get a username from my local server, I got this message on the console:
type 'List<dynamic>' is not a subtype of type 'String'

Performing a debug in the code, I reach this exception:

Map<String, dynamic> _parseResponse(http.Response response) {
...
if (jsonResponse['errors'] != null) {
   throw new Exception(
        'Error returned by the server in the query' + jsonResponse['errors'],
   );
}

But checking the debug information I got the response data back from the server and also got the errors tag in the Json with size 0.

The code checks only if the tag is available in the Json, not if there is any error included. So to fix this issue I propose to change the code to check if there is an error in the list:
if (jsonResponse['errors'] != null && jsonResponse['errors'].value.size>0) {

Query used in the test

String query = """
query user(\$userId:Long) {
  user (id: \$userId) {
    userName
  }
}
""".replaceAll('\n', ' ');

Screenshot
image

Thanks,
Best regards.

How to pass Authorization headers ???

After logged in user, I want to store it in flutter local storage and also want to pass to the server as Authorization header, how can I achieve this so the server can validate user data ???

I am using Prisma server as a GraphQL backend, that requires authenticated user jwt passed in Authorization headers :)

Something that i am writing, would like to contribute ???

Hey there,

I am going to write something awesome but need some contribution, so I thought to share it with you :)
What I am planning to build is a Dashboard for graphql-flutter client :)

The idea is to give user flexibility from writing code & using dashboard to create QUERY, MUTATION and SUBSCRIPTION without even touching a single file or writing a code.

Workflow is to generate a builder which will dynamically create json/yaml file and from that file we can generate .dart file which can be importable in flutter

Dashboard will have 4 sections :

  1. SchemaBuilder
  2. QueryBuilder
  3. MutationBuilder
  4. SubscriptionBuilder

inside SchemaBuilder user can specify schema identifier, fields and condition

for example

  identifier:
       - GET_USERS_SCHHEMA
  fileds:
      - id
      - email
      - profile
           - name
           - mobile
  conditions:
     - user
         - where:
            - mobile ${mobile}

the above yaml generation is for our workflow, the user will have dashboard interface, with input box to fill. from that input a yaml reference like above will be generated and from that yaml a dart file in user libs/dashy/schemas folder will be generated.. yaml for our reference and dart for user, from that dart file he import

this will generate get_users_schema.dart in libs/dashy/schemas

String getUsersSchema = """
  query(\$mobile: String!) {
    user(where: { mobile: \$mobile }) {
      id
      email
      profile {
        name
        mobile
      }
    }
  }
  """
    .replaceAll('\n', ' ');

Update cache after mutation

Is your feature request related to a problem? Please describe.
In Apollo, the client allows you to easily update the cache after a mutation using an update function.

Describe the solution you'd like
A new Mutation object should have accept an update function as a parameter. That update function should include the cache and the data returned from the mutation as parameters. Take the following example:

    _updateCacheAfterCreate(cache, result) {
      var data = cache.readQuery(query: feedQuery);
      data.feed.links.add(result.link);
      cache.writeQuery(query: feedQuery, data: data);
    }

The query runs against the local cache and is then updated with the link result from the mutation using the writeQuery function. This function is passed to Mutation as follows:

Mutation(
  voteMutation, 
  update:_updateCacheAfterCreate,
)

Describe alternatives you've considered
Currently, the UI updates using polling.

Additional context
https://www.howtographql.com/react-apollo/6-more-mutations-and-updating-the-store/

Types generation

I can make a generator for the types, but it would be nice to pass the parameters to the runtime.
I think Dart doesn't allow it, but how could we go towards that full typed approach?
I haven't written a single line of Dart but I liked Flutter a lot, but I'd need to use it with GraphQL. I can help with the GraphQL part but I would need help with Dart.

socketClient is always null

Description of the bug
socketClient is initialized but never set to the actual connection (reference).
This also results in an error when using the subscription-Widget, because socketClient.connect() is called on null.

Reproduction
n/a

Expected behavior
There should be a way to set the SocketClient to the websocket connection reference.

Additional info
It would also be a good idea to update the readme file.

Assuming I didn't miss a thing are the proposals for an alternative implementation?

Mutations

This is a really needed package.

I played around with it and got to talking to a golang dB on mobile that exposes the dB over graphql over JSON RPC.
It was just a quick and dirty smoke test.

Do you have a roadmap or anything as I can see what else needs to be done to your client and help

NoSuchMethodError: The getter 'loader' was called on null.

Describe the bug
not sure what it is ... just trying to run the library

To Reproduce
just ruining the app with basic implantation
this is my code

          new Mutation(
            mutations.signupUserMutation,
            builder: (
              runMutation, { // you can name it whatever you like
              bool loading,
              var data,
              String error,
          }) {
            if (error != '') {
              return new Text(error);
            }
            return new RaisedButton(
              onPressed: () => runMutation({
                'name': 'ali',
                'email': '[email protected]',
                'password': '1qaz1q',
              }),
              child: new Icon(Icons.edit),
            );
            
          },
          onCompleted: (Map<String, dynamic> data) {
                showDialog(
                context: context,
                builder: (BuildContext context) {
                  return AlertDialog(
                    title: Text('Thanks for your star!'),
                    actions: <Widget>[
                      SimpleDialogOption(
                        child: Text('Dismiss'),
                        onPressed: () {
                          Navigator.of(context).pop();
                        },
                      )
                    ],
                  );
                }
              );
            }
          ),

Screenshots
image

Desktop (please complete the following information):

  • OS: windows
  • Version 0.4.1 , 0.5

compiler message: #54 _RawReceivePortImpl._handleMessage (dart:isolate-patch/dart:isolate/isolate_patch.dart:166)
TimeoutException: Request to Dart VM Service timed out: ext.flutter.debugPaint({enabled: false, isolateId: isolates/629662914})TimeoutException: Request to Dart VM Service timed out: ext.flutter.showPerformanceOverlay({enabled: false, isolateId: isolates/629662914})TimeoutException: Request to Dart VM Service timed out: ext.flutter.repaintRainbow({enabled: false, isolateId: isolates/629662914})TimeoutException: Request to Dart VM Service timed out: ext.flutter.timeDilation({timeDilation: 1, isolateId: isolates/629662914})TimeoutException: Request to Dart VM Service timed out: ext.flutter.debugAllowBanner({enabled: true, isolateId: isolates/629662914})TimeoutException: Request to Dart VM Service timed out: ext.flutter.debugPaintBaselinesEnabled({enabled: false, isolateId: isolates/629662914})

Ignore IntelliJ config files and lock files

Are there any thoughts on ignoring the .idea directory (and some of the config files, like .flutter-plugins and graphql.iml) as well as both the main pubspec.lock and the example's pubspec.lock? The Dart guides suggest not including the pubspec.lock on libraries, and the .idea and IntelliJ config files create large diffs when working on small pieces of the project.

Provide Non-caching client / flag for non-cached call.

Is your feature request related to a problem? Please describe.
Not all applications require a cache. In my case I want to always query the latest values for particular operations.

Describe the solution you'd like
A clear interface for implementing a NullCache along side the InMemoryCache

Describe alternatives you've considered
A flag during the query operation to determine if the cache should be parsed.

Additional context
N/A

Enable support for file uploads in mutation

I am a beginner to flutter and dart, and coming from the React Native ecosystem. Firstly, I really appreciate the work you guys are doing!!

I am looking for a way to upload files through graphQL mutations for a personal college project. It would make things very straightforward in terms on handling uploads.

A great starting point could be jaydenseric's implementation of apollo-upload-client https://github.com/jaydenseric/apollo-upload-client

Another way is to handle file uploads separately using http request, but this makes it way messier due to the database mutation and upload being separate requests.

I would really appreciate any help or suggestions, I am trying my best to learn and will contribute back :)

Handle errors even when no location is defined

Describe the bug

When we receive errors from a GraphQL servers, the library builds a GQLError :

GQLError.fromJSON(Map data)
  : message = data['message'],
    locations = new List.from(
        (data['locations']).map((d) => new Location.fromJSON(d))),
    path = data['path'];

As it is defined, this constructor will fail if the jsonResponse doesn't include a location.

But as far as I understand the GraphQL specification ( http://facebook.github.io/graphql/draft/#sec-Errors ), this field is not always mandatory (only "If an error can be associated to a particular point in the requested GraphQL document", but there might be cases where it is not associated to a particular point, for example when the issue is global to the request method itself. And anyway, it says "it should contain an entry with the key locations", and not "it must" that's used for paths)

Expected behavior

Allow request with only a "message" key, or "message" + "path". This should be quite easy, but probably a breaking change for existing users of the library ?

If there is interest in fixing that, I can submit a pull request.

Pass Client object as parameter, or let client object define query methods

Currently, I have code like this:

lib/main.dart:

void main() {
  client = new Client(
    endPoint: 'https://api.github.com/graphql',
    cache: new InMemoryCache(),
  );
  client.apiToken = "...";

  runApp(new MyApp());
}

And somewhere in the app, I will then simply run my query like so:

return Query(
      readRepositories,
...
)

This is very simple, client & query are loosely coupled.
The client variable is actually a global.

I think it would be preferable to not have a global client object, and instead have it available as a (named) parameter to the Query or other objects.

Client could also define newQuery or newMutation methods for convenience.

Query polling

Is this instead of subscriptions ?
Like a pull instead of push ?

A static website for documentation

I think this project deserves some static website for documentation and showcase some use case at the current state. I could volunteer to this at the moment.

Question on implementation practice in a more realistic environment perhaps...

Is your feature request related to a problem? Please describe.
Reading your documentation -- I am not certain how to implement this is my Flutter App. Specifically, our App has quite a long and lengthy signup/login process before we can get the JWT for the Auth token that is needed to access the GraphQL server.

In fact, it's not for a little while before we even know where the GraphQL server side is located...

So it's not feasible to put all that startup logic, etc. in the Main App ...

Also -- our JWTs expire after N minutes and get renewed -- so we need to modify the HttpLink when that happens and have no idea how to do so...

Also -- we currently have quite a bit of code in our scoped-model logic -- and there are places for sure where I'd like to execute some GraphQL queries .. but .. that code really is independent of any Widget per se .. so not sure how to use the GraphQL / client in that context either ...

Describe the solution you'd like

More examples or more documentation on OTHER implementation that don't depend on it happening right at the start -- with variable plugins that can change over time in the same app..

There is probably a way to -- once ready -- do the "init" and grab and save the client to some static class area that can be retrieved later .. and then .. hmm.. use GraphQLClient all over the place (or at least at the highest level Routes?) .. Can it be used within the routing mechanism somehow?

Anyway -- now you can see why I have so many questions on how to actually use this.. ! LOL

Cheers and nice work on this BTW -- We are using ApolloClient in our Vue web app and love it there.. and obviously this looks very promising too !

Passing on variables unsuccessful

Trying to pass on a variable results in a bad request.

I am making the following query, which is successful:

String singleFile = """ query {file(id: "cji4rpaw702zu07920hjzseq4"){ url }} """;

but querying for id in a variable format does not work. Perhaps it is an issue with my code, but I have tried several measures and feel hopeless now.

Here is my code for constructing the query:
String singleFile = """ query {file(id: \$someID){ url }} """;
and here it is inside the component:

Query(singleFile, variables: { 'someID' : "cji4rpaw702zu07920hjzseq4" },

I would really appreciate the help.

Making a dart implimentation of apollo client

Is your feature request related to a problem? Please describe.
No. My feature request is a question/recommendation about the direction of this project.

Describe the solution you'd like
Dart has the ability to be converted to javascript, but has the advantage of types. Considering apollo-client is a javascript/typescript library, in theory it should be possible to implement a version of apollo-client with very similar usage in dart. Considering this, it might be worth directing this project with the goal of having the same usage, project structure and plugable nature as the official apollo-client implementation. This might make it easier for react-js/native flutter converts to pick up this project and use it as their own graphql solution. The apollo team has created a well liked, powerful set of clients for react, android, ios and more, but a flutter solution is needed.

Describe alternatives you've considered
Alternatively this project could continue as is. This feature request is less of a strict request as it is a question about the direction of the project and a proposal as to what direction that could be.

Additional context
Apollo Client issue requesting flutter support
Apollo Client
React Apollo
Apollo Android

Failed assertion: line 77 pos 12: 'client != null': is not true

Describe the bug
My init, graphqlprovider and query are all in TabOneWidget, for which you can assume, its a TAB1 from Parent widget Tabs.

I'm not sure if I implemented something wrong or not but... everytime I switch tabs and come back to Tab1 where I do my Init etc, I'm getting this error and the Query of course, stops working.

E/flutter (  351): [ERROR:flutter/shell/common/shell.cc(181)] Dart Error: Unhandled exception:
E/flutter (  351): 'package:graphql_flutter/src/widgets/query.dart': Failed assertion: line 77 pos 12: 'client != null': is not true.
E/flutter (  351): #0      _AssertionError._doThrowNew (dart:core/runtime/liberrors_patch.dart:40:39)
E/flutter (  351): #1      _AssertionError._throwNew (dart:core/runtime/liberrors_patch.dart:36:5)
E/flutter (  351): #2      QueryState.getQueryResult (package:graphql_flutter/src/widgets/query.dart:77:12)
E/flutter (  351): <asynchronous suspension>
E/flutter (  351): #3      QueryState.initState (package:graphql_flutter/src/widgets/query.dart:51:5)
E/flutter (  351): #4      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3763:58)
E/flutter (  351): #5      ComponentElement.mount (package:flutter/src/widgets/framework.dart:3629:5)
E/flutter (  351): #6      Element.inflateWidget (package:flutter/src/widgets/framework.dart:2919:14)
E/flutter (  351): #7      Element.updateChild (package:flutter/src/widgets/framework.dart:2722:12)
E/flutter (  351): #8      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3665:16)
E/flutter (  351): #9      Element.rebuild (package:flutter/src/widgets/framework.dart:3507:5)
E/flutter (  351): #10     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3634:5)
E/flutter (  351): #11     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3629:5)
E/flutter (  351): #12     ParentDataElement.mount (package:flutter/src/widgets/framework.dart:3967:11)
E/flutter (  351): #13     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2919:14)
E/flutter (  351): #14     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4771:32)
E/flutter (  351): #15     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2919:14)
E/flutter (  351): #16     Element.updateChild (package:flutter/src/widgets/framework.dart:2722:12)
E/flutter (  351): #17     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3665:16)
E/flutter (  351): #18     Element.rebuild (package:flutter/src/widgets/framework.dart:3507:5)
E/flutter (  351): #19     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3634:5)
E/flutter (  351): #20     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3781:11)
E/flutter (  351): #21     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3629:5)
E/flutter (  351): #22     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2919:14)
E/flutter (  351): #23     Element.updateChild (package:flutter/src/widgets/framework.dart:2722:12)
E/flutter (  351): #24     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3665:16)
E/flutter (  351): #25     Element.rebuild (package:flutter/src/widgets/framework.dart:3507:5)
E/flutter (  351): #26     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3634:5)
E/flutter (  351): #27     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3629:5)
E/flutter (  351): #28     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2919:14)
E/flutter (  351): #29     Element.updateChild (package:flutter/src/widgets/framework.dart:2722:12)
E/flutter (  351): #30     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3665:16)
E/flutter (  351): #31     Element.rebuild (package:flutter/src/widgets/framework.dart:3507:5)
E/flutter (  351): #32     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3634:5)
E/flutter (  351): #33     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3781:11)
E/flutter (  351): #34     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3629:5)
E/flutter (  351): #35     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2919:14)
E/flutter (  351): #36     Element.updateChild (package:flutter/src/widgets/framework.dart:2722:12)
E/flutter (  351): #37     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3665:16)
E/flutter (  351): #38     Element.rebuild (package:flutter/src/widgets/framework.dart:3507:5)
E/flutter (  351): #39     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3634:5)
E/flutter (  351): #40     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3781:11)
E/flutter (  351): #41     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3629:5)
E/flutter (  351): #42     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2919:14)
E/flutter (  351): #43     Element.updateChild (package:flutter/src/widgets/framework.dart:2722:12)
E/flutter (  351): #44     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4666:14)
E/flutter (  351): #45     Element

Expected behavior
To not throw an error?

Additional context

  • does GraphqlProvider really have to be a parent of MaterialApp or can it be parent of one of my sub-widgets?

Any help would be awesome.

Consider not mutating client

Problem

I think the way client is being initialized by mutating global variable inside the library is bad and confusing, and will eventually bite someone. I recently, out of habit of making everything final, made the client final and wasted time figuring out what was wrong.

Proposed Solution

Let users create their own client and add methods like query and mutation in it like Apollo Client does. Also let the user specify token in the constructor itself instead of setting it later.

How to update cache after editing data ???

I have a UpdateProfileScreen which is populated from graphql backend and when I update data.. inside graphql database it is updating.. but when I go back and come again to profile page, the value is older, I have to force close app and reopen.. then only i can see the changes :)

Run Query manually just like Mutation

As we can trigger Mutation on CLICK event, how can do such thing for Quering ???

Like I am building a search functionality, which takes keywords and then search that data in database, but currently only Mutation can be triggered on events like keypress, keyenter etc..

everytime user type in search input I want to make a Query, in apollo we can pass WithApollo and then use this.props.client.query, how to handle such things ???

Using Mutation throws exception (type '(Map<String, dynamic>) => void' is not a subtype of type '(Map<String, dynamic>) => Future<void>)

Describe the bug

When user clicks on button, the mutation should be sent. However, button isn't even shown. The error appears.

Keep in mind, I do not get any lint errors.

I/flutter (12453): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (12453): The following assertion was thrown building Mutation(dirty, state: MutationState#ebddc):
I/flutter (12453): type '(Map<String, dynamic>) => void' is not a subtype of type '(Map<String, dynamic>) =>
I/flutter (12453): Future<void>'
I/flutter (12453):
I/flutter (12453): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter (12453): more information in this error message to help you determine and fix the underlying cause.
I/flutter (12453): In either case, please report this assertion by filing a bug on GitHub:
I/flutter (12453):   https://github.com/flutter/flutter/issues/new
I/flutter (12453):
I/flutter (12453): When the exception was thrown, this was the stack:
I/flutter (12453): #0      MutationState.build (package:graphql_flutter/src/widgets/mutation.dart:80:7)
I/flutter (12453): #1      StatefulElement.build (package:flutter/src/widgets/framework.dart:3743:27)
I/flutter (12453): #2      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3655:15)
I/flutter (12453): #3      Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
I/flutter (12453): #4      ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3635:5)
I/flutter (12453): #5      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3782:11)
I/flutter (12453): #6      ComponentElement.mount (package:flutter/src/widgets/framework.dart:3630:5)
I/flutter (12453): #7      Element.inflateWidget (package:flutter/src/widgets/framework.dart:2920:14)
I/flutter (12453): #8      Element.updateChild (package:flutter/src/widgets/framework.dart:2723:12)
I/flutter (12453): #9      SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4667:14)
I/flutter (12453): #10     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2920:14)
I/flutter (12453): #11     Element.updateChild (package:flutter/src/widgets/framework.dart:2723:12)
I/flutter (12453): #12     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4667:14)
I/flutter (12453): #13     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2920:14)
I/flutter (12453): #14     Element.updateChild (package:flutter/src/widgets/framework.dart:2723:12)

To Reproduce

                new Container(
                  padding: EdgeInsets.all(ThemeSettings.PADDING_DEFAULT / 2),
                  height: 60.0,
                  width: double.infinity,
                  child: new Mutation(
                    GraphQl.setMarketTariff(Data.tariffData),
                    builder: (
                      foo, {
                      bool loading,
                      var data,
                      Exception error,
                    }) {
                      return new FlatButton(
                        color: Colors.white,
                        disabledColor: Theme.of(context).disabledColor,
                        onPressed: _tabController.index == _usedTariff
                            ? null
                            : () {
                                foo({
                                  'foo': 'bar'
                                });
                              },
                        child: new Text(
                          DemoLocalizations.of(context)
                              .get(_tabController.index == _usedTariff
                                  ? 'TARIFF.SELECTED'
                                  : 'TARIFF.USE')
                              .toUpperCase(),
                          style: new TextStyle(
                              color: _tabController.index == _usedTariff
                                  ? Colors.white
                                  : Colors.black,
                              fontSize: 18.0),
                        ),
                      );
                    },
                    onCompleted: (Map<String, dynamic> data) {
                      print("COMPLETED $data");
                    },
                  ),
                )

Expected behavior
Show button properly.

Screenshots
image

Without mutation, the FlatButton should show.

▶ flutter --version
Flutter 0.6.0 • channel beta • https://github.com/flutter/flutter.git
Framework • revision 9299c02cf7 (3 weeks ago) • 2018-08-16 00:35:12 +0200
Engine • revision e3687f70c7
Tools • Dart 2.1.0-dev.0.0.flutter-be6309690f

graphql-flutter version in pubspec.yaml:  graphql_flutter: ^0.9.1

Also, it would be good to provide the same functionality as with queries where I can simply call:

    Client client = GraphQl.client.value;
    client
        .query(query: GraphQl.getTariffInformation())

So that we could call:

    Client client = GraphQl.client.value;
    client
        .mutation(mutation: GraphQl.setTariffInformation())

How to decode UTF-8 chars in response?

We have a Cyrillic (Mongolian) texts returned from GraphQL API.

But Cyrillic texts are obscured. Something like this.
screen shot 2018-09-11 at 4 30 37 pm

We write a custom UTF-8 converter.

static String utf8convert(String text) {
    List<int> bytes = text.toString().codeUnits;
    return utf8.decode(bytes);
}

And the result is here
screen shot 2018-09-11 at 4 35 19 pm

Separate generic GraphQL client code from flutter implementation

Is your feature request related to a problem? Please describe.
When trying to use Graphql-flutter in a framework-agnostic way, it is today possible to target directly non-Flutter specific parts (Client, ...) of this library, which is probably the best in Dart as of today.

For example, following the BLoC pattern, we use graphql-flutter inside our business logic components that (even if used today with Flutter) are intended to be framework-agnostic (and could be used with AngularDart for example ?).

The problem is that, making a separate Dart package for this business logic components, a dependency on graphql-flutter would bring a dependency on Flutter itself, even if we're not using Flutter-specific parts of the package.

Describe the solution you'd like
Separate this wonderfull lib in 2 packages : 1 framework-agnostic with generic GraphQL, and another one with Flutter implementation targetting the first one

Describe alternatives you've considered
If this is not intended, we would probably create a new library based on the "generic" GraphQL implementation from this library. This would probably bring some overhead in maintaining synchronization between the 2 projects contributions.

Test Server

It would be nice if a basic test server in whatever language could be added to the repo.

It would help me with seeing what the Dart code expects to get from the server and also see patterns of usage.

Don't send Authorization header if token is null

Describe the bug
Currently it seems like that the library is sending the Authorization header regardless if the apiToken is set by the user or not. This leads to a header which looks like this: Authorization: Bearer null. It might be cleaner to omit the header alltogether if the apiToken is null/undefined.

To Reproduce
Steps to reproduce the behavior:

  1. Define the client without "apiToken"
  2. Make a request
  3. Header is sent as Authorization: Bearer null

Expected behavior
No Authorization header is sent at all, since there was no intend to authorize

Subscription connection_init doesn't send any payload

Describe the bug
When creating a subscriber, the payload should send the payload too. This is, per default, done by apollo-client:

image

To Reproduce
Steps to reproduce the behavior:

  1. make a connection (your graphql server should require an authentication!)
    final String authHeader = "${Auth.authMode} ${Auth.accessToken}";
    SocketClient socketClient = await SocketClient
    .connect(Static.BASE_URL_GRAPHQL,
      headers: {
        HttpHeaders.authorizationHeader: authHeader
      },
    );

    socketClient
    .subscribe(SubscriptionRequest(operationName, query, null))
    .listen(print);
  1. you will get any kind of error since the server awaits the accessToken in the payload data.

Expected behavior
No exception.

Screenshots
Screenshot from apollo in description above.

Desktop (please complete the following information):

  • OS: Windows/Mac
  • Browser Why browser?
  • Version 0.9.1

Smartphone (please complete the following information):

  • Device: Samsung Galaxy S8, iPhone X, Google Pixel 2XL
  • OS: Android 8.0, 9.0, iOS 11.4
  • Browser Flutter app
  • Version /

Additional context
As said, with .connect() method, we should have at least an option to pass the payload (Map<String, dynamic>) which should then be sent as payload when connection_init is being done.

Hooking up to graphql server

I noticed your not supporting subscriptions.
So the query polling instead I presume.

I am hooking the dart front end up with a golang server and so just need to design for your approach.

Thanks in advance

Authentication Header should be more flexible

Is your feature request related to a problem? Please describe.
Different backends require API token to passed with different pre parameters currently

  Map<String, String> get headers => {
        'Authorization': 'Bearer $apiToken',
        'Content-Type': 'application/json',
      };

the authorization header is fixed no alternative is possible, for example, I want the header to look like

"Authorization: JWT <your_token>"

Describe alternatives you've considered
The client API token could be
'Authorization': '$apiToken',
so that we can add any additional statement according to our requirement, but this should be backward compatible.

Need of flutter?

I was trying to make a CLI client that would require the use of GraphQL. But, I don't see the need of this library to use Flutter.
Would it be possible to remove Flutter as a dependency or something is required for this library to work, which uses Flutter?

I'll try removing Flutter as a dependency, but that would take some time( depending on how much free time I get ). So, any other ideas to get this working without Flutter or has anyone already done it?

P.S:- I'll soon try it with Flutter, 'cause this library seems pretty amazing 😃

Include tests and implement CI

Is your feature request related to a problem? Please describe.
There currently is no way to programatically determine if pushed commits still provide a stable API. We require a peer for each PR, but some bugs might still slip trough.

Describe the solution you'd like
I suggest to create Unit Tests with a least 80% coverage. In addition I suggest to implement an automated build and deploy pipeline.

Additional context

  • Write tests
  • Setup automated builds

Cannot specify charset on 'Content-Type' header

To Reproduce
Querying a graphql endpoints that returns accents such as "Belvédère". Instead we get a string with "Belvédère"

Expected behavior
Find the string "belvédère" in the jsonResponse Map after decoding (line 76 client.dart).

final Map<String, dynamic> jsonResponse = json.decode(response.body);

The header parameters are hardcoded and the 'Content-Type' is set to application/json.
In order to support the accents we should be able to specify the charset such as:
'Content-Type: application/json; charset=utf-8'

According to dart documentation:

/// The body of the response as a string. This is converted from [bodyBytes]
  /// using the `charset` parameter of the `Content-Type` header field, if
  /// available. If it's unavailable or if the encoding name is unknown,
  /// [latin1] is used by default, as per [RFC 2616][].
  ///
  /// [RFC 2616]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
  String get body => _encodingForHeaders(headers).decode(bodyBytes);

Data from partially successful queries is not returned

Describe the bug
If a named query contains an error, data from successfully executed subqueries is simply discarded.

I have a similar query to this:

query getStats {
  statusA: getSystemStatusA {
    uptime
    cpuLoad
  }
  statusB: getSystemStatusB {
    uptime
    cpuLoad
  }
  statusC: getSystemStatusC {
    uptime
    cpuLoad
  }
}

which returns this result:

{
  "errors": [
    {
      "message": "error message",
      "locations": [
        {
          "line": 10,
          "column": 3
        }
      ],
      "path": [
        "statusB"
      ]
    },
  ],
  "data": {
    "statusA": {
      "uptime": 123,
      "cpuLoad": 6.25,
    },
    "statusB": null,
    "statusC": {
      "uptime": 456,
      "cpuLoad": 6.25,
    }
  }
}

Expected behavior
I'd expect to receive the errors and the data without an exception. I'd only expect an exception if the http status code is not 200.

Additional context
Problem is a bit of code in client.dart[78]

Is there any special reason to drop all the data? I'd like to show an appropriate error message in my app ui for the failed queries.

My current simplistic solution is to comment out the if block and just return the whole JSON object, including all errors.

    final Map<String, dynamic> jsonResponse = json.decode(response.body);
    return jsonResponse;
    
    /*     
    if (jsonResponse['errors'] != null && jsonResponse['errors'].length > 0) {
      throw GQLException(
        'Error returned by the server in the query',
        jsonResponse['errors'],
      );
    } 

    return jsonResponse['data'];
    */

Thanks!

What makes this package better than any other package?

Hello,

What makes this package better than any other package?
In other words, why shall I consider using your package over any other package?

I am confused as I found 3 or more packages for GraphQL and Flutter, and I don't know which package to start with.

Optimistic results PR

@HofmannZ is anyone working on the optimistic results PR or can I take it up?

Also, would like to know the requirements/guidelines before getting starting on it :)

Run query in a MV* pattern

Right now, if I understand correctly the query is a widget so it's building the UI with the result of the query.

Is it possible to run a query outside of a widget and just fet the result ?

upgraded to alpha-1.0.0

hello,

in previous version I was able to set apiToken

final Client client = GraphqlProvider.of(context).value;
final SharedPreferences preferences = await SharedPreferences.getInstance();
const token = preferences.getString('authToken');
client.apiToken = token;

from authentication.dart page

but now client.link says, its final, can't change it.
how can i set headers ???

Also main.dart file does not support async function so that i can't use something like:-

final SharedPreferences preferences = await SharedPreferences.getInstance();
const token = preferences.getString('authToken');

HttpLink link = HttpLink(
      uri: 'http://192.168.2.200:4000',
      headers: <String, String>{
        'Authorization': token,
      },
    );

Support custom error response extensions

Is your feature request related to a problem? Please describe.
Our GraphQL API returns customized data in error extensions. This plugin catches errors and parses them into aGQLException which includes a GQLError. This is convenient but the GQLError does not include the extensions object. Apollo documentation here: https://www.apollographql.com/docs/apollo-server/v2/features/errors.html. I need to be able to extract the error information as-is from the library.

Describe the solution you'd like
Add a simple Map<String, dynamic> extensions object to GQLError so that the host application can read the data when needed.

Describe alternatives you've considered
I don't know of any alternatives. Extensions are free-form so we can't build in a model witch which to parse them.

Additional context
none.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.