Libraries supporting GraphQL in Dart

Overview

gql-dart/gql

MIT License PRs Welcome Watch on GitHub Star on GitHub Watch on GitHub Discord

This is an effort to advance the Dart GraphQL ecosystem.

It consists of multiple packages and libraries centered around GraphQL AST.

Packages

Core

The core of this project is the GraphQL parser which parses GraphQL strings into an AST. The parsed AST can then be transformed, visited and printed back to GraphQL string.

Pub Package Library Description
version package:gql ast.dart GraphQL AST implementation with Visitor pattern and AST transformer
version package:gql language.dart GraphQL source parser and printer. Recognizes both operations and SDL
version package:gql document.dart Document and schema validation

Code generation

GraphQL language enables code generation to speed up development and move document processing to build-time.

We provide code builders to generate Dart source code and file builders which easily plug into standard Dart code generation pipeline.

Ideas for future work:

  • Typed resolvers for field resolution on the client or server
Pub Package Library Description
version package:gql_code_builder Various builders
version package:gql_build File builders

Client

To enable development of GraphQL clients, we provide type definitions used to execute GraphQL operations. They include AST-based operation, request with per operation context, and response. These types are used by the Links.

Link is the current client implementation. Link is GraphQL AST-aware request/response middleware. They can be used to build a pipeline to deduplicate requests, conditionally transform requests and responses (including the context), and eventually send the requests to the server.

Ideas for future work:

  • websocket link for subscriptions
  • batched request HTTP link
  • retry link to handle network issues transparently
  • link for client-side request resolution
Pub Package Library Description
version package:gql_exec gql_exec.dart Implementation of types for GraphQL requests and responses
version package:gql_link link.dart Base for modular GraphQL execution interface
version package:gql_http_link gql_http_link.dart Link to execute GraphQL requests via HTTP
version package:gql_dedupe_link gql_dedupe_link.dart De-duplicating Link to avoid execution of identical requests
version package:gql_transform_link gql_transform_link.dart GQL Link to transform Requests and Responses. May be used to update context, document, variables, data, errors, etc.
version package:gql_websocket_link gql_websocket_link.dart GQL Link for subscriptions using websocket.
version package:gql_dio_link gql_dio_link.dart Similar to gql_http_link, A GQL Terminating Link to execute requests via Dio using JSON.

Other

Pub Package Library Description
version package:gql_pedantic Lint rules used by all gql-dart/gql packages

Examples

Pub Package Library Description
version package:gql_example_cli Example usage in a CLI environment
version package:gql_example_flutter Example usage in a Flutter environment

Users

Project Description
artemis Build dart types from GraphQL schemas and queries (using Introspection Query).
graphql A stand-alone GraphQL client for Dart, bringing all the features from a modern GraphQL client to one easy to use package.
graphql_flutter A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.
normalize Normalization and denormalization of GraphQL responses in Dart
ferry GraphQL Client for Dart
graphql_server Base package for implementing GraphQL servers.
graphql-to-dart generate dart classes and respective JsonSerializable transcoders (npm package)
major_graphql generate built_value classes and serializers with pub build (successor of graphql-to-dart)
Your project? Open a PR to add it to this readme!

Contributing

The goal of this project is to expand Dart GraphQL ecosystem and to build a community around this vendor-neutral implementation.

Community contributions are welcome.

multipack

This repo uses multipack. To activate it run the following command.

pub global activate multipack

multipack provides a simple way of running commands in multiple packages at once. It builds a directed graph of packages to run commands in topological order.

Link all local packages by running

multipack pubspec override

Get all packages by running

multipack pub get

Clean up the pubspec file before publishing

multipack pubspec clean

See more usage examples in .github/workflows/dart.yml.

Features and bugs

Please file feature requests and bugs at the GitHub.

Comments
  • [gql_build] Add immutability features

    [gql_build] Add immutability features

    I just wanted to start a discussion about the possibility of building data as built_values rather than storing the Json object and using getters.

    I find the immutability and serializability of built_value to be compelling, although it would add some complexity.

    Thoughts?

    opened by smkhalsa 24
  • WIP: Code Generators

    WIP: Code Generators

    Extends the set of code builders available.

    ast_builder

    Generates an AST representation of a GraphQL Document

    data_builder

    Generates a typed view on top of data JSON. The generated classes are not supposed to be used directly as that would introduce tight coupling between your GraphQL documents and your application code.

    class $ListPokemon {
      const $ListPokemon(this.data);
    
      final Map<String, dynamic> data;
    
      List<$ListPokemon$pokemons> get pokemons => (data["pokemons"] as List)
          .map((dynamic e) => $ListPokemon$pokemons(e as Map<String, dynamic>))
          .toList();
    }
    
    class $ListPokemon$pokemons {
      const $ListPokemon$pokemons(this.data);
    
      final Map<String, dynamic> data;
    
      String get id => data["id"] as String;
      String get name => data["name"] as String;
    }
    

    op_builder

    Wraps AST and operation name into an Operation.

    import 'package:gql_exec/gql_exec.dart';
    import 'find_pokemon.ast.gql.dart' as find_pokemon;
    
    const FindPokemon = Operation(
      document: find_pokemon.document,
      operationName: 'FindPokemon',
    );
    

    req_builder

    Extend Request class to use specific Operation and provide ability to build variables. Builder pattern let's you handle nullable variables correctly (GraphQL spec pretty much requires both undefined and null values).

    import 'package:gql_exec/gql_exec.dart' as _i1;
    import 'find_pokemon.op.gql.dart' as _i2;
    
    class FindPokemon extends _i1.Request {
      FindPokemon()
          : super(operation: _i2.FindPokemon, variables: <String, dynamic>{});
    
      set name(String value) => variables["name"] = value;
    }
    

    enum_builder

    Generates an enum-like class per GraphQL enum type. Defines known enum values to be used in your code, and allows unknown enum values to be used without causing runtime error when handling response data.

    class ReleaseType {
      const ReleaseType(this.value);
    
      final String value;
    
      static const ReleaseType ALPHA = ReleaseType('ALPHA');
    
      static const ReleaseType BETA = ReleaseType('BETA');
    
      static const ReleaseType GAMMA = ReleaseType('GAMMA');
    
      @override
      int get hashCode => value.hashCode;
      @override
      bool operator ==(Object o) => o is ReleaseType && o.value == value;
    }
    

    scalar_builder

    Generates a container for a scalar value to be used when viewing the response data and building request variables.

    class ID {
      const ID(this.value);
    
      final String value;
    
      @override
      int get hashCode => value.hashCode;
      @override
      bool operator ==(Object o) => o is ID && o.value == value;
    }
    

    input_builder

    Generates an input builder to be used to build request variables.

    class MutationInput {
      final Map<String, dynamic> input = <String, dynamic>{};
    
      set a(String value) => input['a'] = value;
    }
    

    schema_builder

    Combines enum_builder, input_builder and scalar_builder.

    Usage example

    final result = await link.request(
      FindPokemon()..name = "Charizard",
    );
    final data = $FindPokemon(result.data);
    
    final pokemon = data.pokemon;
    
    print("Found ${pokemon.name}");
    print("ID: ${pokemon.id}");
    
    final weight = pokemon.weight;
    final height = pokemon.height;
    
    print(
      "Weight: ${weight.minimum} – ${weight.maximum}",
    );
    print(
      "Height: ${height.minimum} – ${height.maximum}",
    );
    
    package/gql_code_gen package/gql_example_cli package/gql_code_builder package/gql_build 
    opened by klavs 19
  • bump analyzer 2.2.0

    bump analyzer 2.2.0

    Hi @smkhalsa I'm pingin you cause you was the last who contributed to gql_code_builder I'm helping @comigor to maintain artemis

    We would like to update our deps to latest version but we cannot due to analyzer: 1.2.0 dep in gql_code_builder

    I made this PR to update ananlyzer to latest version.

    I also added some fixes for failing actions - mostly dependency reordering.

    I would appreciate if you merge and release my PR.

    Thanks

    opened by vasilich6107 18
  • Expression - A non-null value must be returned

    Expression - A non-null value must be returned

    Hello, recently when running dart run build_runner build in order to get graphql query and mutation methods generated by Artemis, I am receiving this error on my build server (Codemagic) but not on my local machine. I have verified the package versions used are the same. Is it possible this package content changed without a bump in version number?

    [INFO] Generating build script...
    [INFO] Generating build script completed, took 803ms
    
    [INFO] Precompiling build script......
    [WARNING] ../../../.pub-cache/hosted/pub.dartlang.org/gql_code_builder-0.3.0-alpha+1635885531709/lib/src/ast.dart:618:12: Error: A non-null value must be returned since the return type 'Expression' doesn't allow null.
     - 'Expression' is from 'package:code_builder/src/specs/expression.dart' ('../../../.pub-cache/hosted/pub.dartlang.org/code_builder-4.1.0/lib/src/specs/expression.dart').
    Expression _directiveLocation(DirectiveLocation location) {
               ^
    [INFO] Precompiling build script... completed, took 11.6s
    
    [SEVERE] Failed to precompile build script .dart_tool/build/entrypoint/build.dart.
    This is likely caused by a misconfigured builder definition.
    
    opened by ecoant 17
  • Error when parsing SDL schema

    Error when parsing SDL schema

    Hey @klavs! I'm getting an error while using the language SDL parser (parseString) on some of my examples. It say it can't find the Entity interface while parsing the Area object even though it's declared on the same schema:

    Error on line 32, column 28 of lib/graphbrainz.schema.graphql: Unknown definition type 'Entity'
       ╷
    32 │ type Area implements Node, Entity {
       │                            ^^^^^^
       ╵
    package:gql/src/language/parser.dart 175:5   _Parser._parseDefinition
    package:gql/src/language/parser.dart 117:22  _Parser._parseMany
    package:gql/src/language/parser.dart 142:22  _Parser._parseDocument
    package:gql/src/language/parser.dart 41:27   _Parser.parse
    package:gql/src/language/parser.dart 17:17   parse
    package:gql/src/language/parser.dart 27:5    parseString
    

    The full schema, for referece: graphbrainz.schema.graphql.

    opened by comigor 15
  • Null Safety

    Null Safety

    Supersedes #193 as the nullsafety tracking PR. Will remain a draft and reference point for prereleases until dart has a stable null safe release. @klavs am planning on publishing *-nullsafety.0 versions for migrated packages soon, so that downstream packages can begin migrating.

    Null safety migrations run thus far:

    Libraries

    ~~blocked by https://github.com/dart-lang/build/issues/2920~~

    • [x] gql_code_builder
    • [x] gql_build

    Examples

    • [X] cats
    • [x] gql_example_cli
    • [x] gql_example_cli_github
    • [x] gql_example_build
    • [x] gql_example_http_auth_link
    • [x] gql_example_dio_link
    • [x] gql_example_flutter

    stable release TODOs

    opened by micimize 14
  • Extract http client from http link, allowing custom clients (dio)

    Extract http client from http link, allowing custom clients (dio)

    This WIP-PR that aims to solve the issue discussed in #154.

    The old API will remain almost the same. HttpLink default constructor will create a new HttpGqlClient. The HttpLinkParserException & HttpLinkServerException will now take the abstracted GqlClientResponse type instead of the http lib type.

    All tests are passing, but the test that depend on the http.Response type in the exceptions.

    Suggestions for how to improve the new API are more than welcome.

    opened by TarekkMA 14
  • Update analyzer version

    Update analyzer version

    Update the analyzer package from ^0.39.14 to ^0.40.4.

    Advantages:

    • Quite some open issues are fixed
    • gql_code_builder would be now compatible with the latest version of build_runner (^1.10.3)

    EDIT: This PR is blocked, waiting for the new release of build_value_generator. More info here

    opened by lucaspal 13
  • Bring Links up to par with what package:graphql has

    Bring Links up to par with what package:graphql has

    • [x] Example of Auth link functionality
    • [x] Error Link
    • [x] Websocket Link
    • [x] File upload
    • [x] http_link should have something like the useGETForQueries option as well
    • [ ] persisted queries were recently contributed
    opened by klavs 12
  • type '(dynamic) => Map<String, dynamic>?' is not a subtype of type '(dynamic) => FutureOr<Map<String, dynamic>>?' of 'function result'

    type '(dynamic) => Map?' is not a subtype of type '(dynamic) => FutureOr>?' of 'function result'

    Hi there! I left my app open overnight, and ended up with over four thousand (4000!) errors originating from this package with the error message type '(dynamic) => Map<String, dynamic>?' is not a subtype of type '(dynamic) => FutureOr<Map<String, dynamic>>?' of 'function result'.

    I've seen this error before but haven't thought much of it until I began getting messages from sentry about over use. Here's a small stack trace that sentry gives me:

    link.dart in WebSocketLink._parseSocketMessage within gql_websocket_link
    link.dart in WebSocketLink._connect.<fn> at line 206:37 within gql_websocket_link
    link.dart in WebSocketLink._connect.<fn> at line 201:31 within gql_websocket_link
    

    and here are my versions:

      gql: 0.13.0
      gql_link: ^0.4.0
      gql_http_link: ^0.4.0
      ferry_flutter: ^0.5.4
      gql_exec: ^0.3.0
      gql_websocket_link: ^0.3.1
    

    is this seen anywhere? how can I fix this error? Thanks!

    opened by antholeole 11
  • Multipart File Upload and useGETForQueries support

    Multipart File Upload and useGETForQueries support

    This extracts the logic for multipart file upload and useGETForQueries from graphql/client.dart, with accompanying tests

    Major changes:

    • useGetForQueries argument to HttpLink
    • using http.Client.send instead of post
    • HttpLink stores uri as a Uri
    • I reworked HttpLink._serializeRequest into an exception handling HOF to handle the different paths, but really I think RequestSerializer should have a generic Serialized type which is http.BaseRequest for HttpLink. Otherwise it can't really handle the serialization concern IMO

    This addresses some of #57

    opened by micimize 11
  • HttpLinkServerException (ServerException) contains parsedResponse

    HttpLinkServerException (ServerException) contains parsedResponse

    When looking at the docs for HttpLinkServerException it has the following text:

    /// Exception occurring when network fails
    /// or parsed response is missing both `data` and `errors`. <--- parsedResponse should have missing data and errors
    

    Is this true? I get exceptions thrown with HttpLinkServerException that contains the parsedResponse.

    In this case it has the following information:

    // the below code is thrown when we catch for `HttpLinkServerException`
    ServerException(
      originalException: null, 
      parsedResponse: Response(
        data: null, errors: [GraphQLError(message: unauthenticated, locations: null, path: null, extensions: {code: AUTHENTICATION_ERROR, statusCode: 401})], context: Context({ResponseExtensions: Instance of 'ResponseExtensions'}), response {errors: [{message: unauthenticated, extensions: {code: AUTHENTICATION_ERROR, statusCode: 401}}]}
      )
    )
    

    I don't have a good way currently to reproduce this more than seeing it logged to Sentry. I could also misunderstand this, so would love some input!

    opened by RobertBrunhage 4
  • Add a way to check whether a `Request` is a query or a mutation

    Add a way to check whether a `Request` is a query or a mutation

    Currently, there's no easy way to check whether a Request is a query or a mutation.

    This leads to code duplication, as seen below:

    https://github.com/gql-dart/gql/blob/c13e2fe2e6ca234ff5bc17263e3536ed2c907474/links/gql_dio_link/lib/src/_utils.dart#L85-L101

    https://github.com/gql-dart/gql/blob/c13e2fe2e6ca234ff5bc17263e3536ed2c907474/links/gql_http_link/lib/src/_utils.dart#L7-L23

    I can also see this being very useful for other developers for doing conditional checks based on queries/mutations.

    opened by ueman 1
  • Transport ws protocol

    Transport ws protocol

    Closes https://github.com/gql-dart/gql/issues/305.

    Hi this PR implements the graphql-transport-ws subprotocol. The code is a direct port of https://github.com/enisdenjo/graphql-ws/blob/master/src/client.ts with some changes to implement the Link interface and replace some JavaScript patterns to what one would expect in Dart. There is still some work to be done, at the moment there are some TODO comments and print statements in the code, some of the comments reference the JavaScript API and the tests for the apollo part are failing. I think some timer is being executed multiple times when the expectAsyncN function only expects a single execution. When trying to reconnect to the server, for example. However, the core logic works and is fully tested most of the changes that need to be done are about the external API or cleaning up comments.

    I created a _testLinks function in the test file to test both subprotocols using the same logic. However, that makes it harder to test it in vscode since the extension does not recognize the test prefix associated with each subprotocol. One can use the dart test --name "transport ws sub-protocol <test-name>" cli, but I am not sure if we should try to split it so it is easier to debug.

    At the moment, there are two separate Link implementations, with somewhat different parameters. Not sure what could be the best approach here, maybe we could try to unify some of the constructor parameters.

    When a message of type "error" is encountered, the request stream throws an error with the payload (a list of GraphQLError). The behavior is different from the apollo protocol where multiple errors can be sent as regular events within the stream. We could do the same, the exact line is here. However, I believe there would be no easy way to distinguish between a message of type "error" and type "next" with errors payload as an end user. According to the spec, the type "error" ends the request, no more messages should be sent.

    I have tested it end to end with a https://github.com/juancastillo0/leto server.

    Thanks!

    opened by juancastillo0 3
  • [codegen] separate reserved names for top identifiers and reserved names for built_value fields

    [codegen] separate reserved names for top identifiers and reserved names for built_value fields

    Right now, there is onelist of reserved names which get escaped when used as an identifier. This list includes reserved keywords in dart (like class) and names which are reserved by built_value (like 'toJson') and cannot be used as name for a field in built_value.

    Since we also generate top-level constants, this single list is too restrictive and might lead to escaping of names when it is not needed.

    Example: It is valid to define a top-level constant with the name 'rebuild', but we would still escape the name of the top-level constants which is generated from a directive like

    directive @rebuild on FIELD_DEFINITION
    

    to Grebuild

    package/gql_code_gen 
    opened by knaeckeKami 0
  • Graphviz dot produces indeterminsitic result, breaking the CI SVG check

    Graphviz dot produces indeterminsitic result, breaking the CI SVG check

    repeat 20 multipack info | dot -Tsvg -x | md5
    

    outputs

    2db5aa6b11b6b4f52e8283f2435d5212
    d6156c52000e690a7c3e72e52553b9db
    2db5aa6b11b6b4f52e8283f2435d5212
    2db5aa6b11b6b4f52e8283f2435d5212
    1979929664b2fbc1bce4975000f37ac3
    5201338dd5c626e72645bbcedf9ea4bf
    5201338dd5c626e72645bbcedf9ea4bf
    2db5aa6b11b6b4f52e8283f2435d5212
    5201338dd5c626e72645bbcedf9ea4bf
    2db5aa6b11b6b4f52e8283f2435d5212
    2db5aa6b11b6b4f52e8283f2435d5212
    2db5aa6b11b6b4f52e8283f2435d5212
    5201338dd5c626e72645bbcedf9ea4bf
    5201338dd5c626e72645bbcedf9ea4bf
    5201338dd5c626e72645bbcedf9ea4bf
    5201338dd5c626e72645bbcedf9ea4bf
    5201338dd5c626e72645bbcedf9ea4bf
    2db5aa6b11b6b4f52e8283f2435d5212
    5201338dd5c626e72645bbcedf9ea4bf
    1979929664b2fbc1bce4975000f37ac3
    

    on my machine. It should output the same hash every time if the algorithm was deterministic. The output of multipack info is deterministic, so it must be dot which is the culprit here. The actual difference in the SVG is tiny, it seems to come down to some rounding differences.

    I believe this is a known issue of dot discussed here: https://gitlab.com/graphviz/graphviz/-/issues/1767

    Because of this, the check SVG step in the CI does not really make sense in my opinion, since it would often fail even though the SVG image is up to date.

    opened by knaeckeKami 0
Owner
GQL Dart
GraphQL tools for Dart
GQL Dart
Build dart types from GraphQL schemas and queries

Artemis Build dart types from GraphQL schemas and queries Check the beta branch for the bleeding edge (and breaking) stuff. Artemis is a code generato

Igor Borges 481 Nov 27, 2022
Tooling and libraries for processing dart test output into dev-friendly formats

better_test_reporter Introduction This is an application/library heavily inspired by dart-junitreport and dart-testreport. It takes what was done in t

Betterment 6 Sep 14, 2022
The Dart SDK, including the VM, dart2js, core libraries, and more.

Dart A client-optimized language for fast apps on any platform Dart is: Optimized for UI: Develop with a programming language specialized around the n

Dart 8.7k Jan 2, 2023
Venni client app - A flutter ride-sharing end-user app supporting map location picking

Venni client app - A flutter ride-sharing end-user app supporting map location picking, driver location tracking, in-app credit card payments, trip rating system, and trip history.

Abrantes 1 Jan 3, 2022
tmodinstaller - A beautiful mod installer for minecraft supporting custom repositories and more

tmodinstaller A beautiful mod installer for minecraft supporting custom repositories and more. TMod Installer is a cross platform mod installer and up

Tricked 16 Aug 28, 2022
A Dart library for creating a Dart object to represent directory trees.

Directory Tree A Dart library for creating a Dart object to represent directory trees. Getting Started Import and initialize package import 'package:d

Chiziaruhoma Ogbonda 5 Dec 1, 2021
A collection of Dart code samples by Dart DevRel

Dart samples A collection of Dart programs that illustrate features and best practices. For a list of community-maintained projects, see Awesome Dart.

Dart 458 Dec 30, 2022
A discord bot, made with Dart, which lets you run your own pure Dart code snippets directly via a discord ping, and get the output in an instant.

A discord bot, made with Dart, which lets you run your own pure Dart code snippets directly via a discord ping, and get the output in an instant.

Anikate De 3 Oct 21, 2022
A multiplatform Dart movie app with 40% of code sharing between Flutter and the Web.

A multiplatform Dart movie app with 40% of code sharing between Flutter and the Web.

Iiro Krankka 3.4k Dec 30, 2022
server side dart micro-framework to handle incoming http requests

Queen Palace ???? Introduction server side dart micro-framework to handle incoming http requests

Ahmed Masoud 32 Aug 30, 2022
Nhost Dart & Flutter packages

Nhost Packages for Dart & Flutter Package nhost_sdk Dart authentication and file storage API clients nhost_flutter_auth Flutter widgets for exposing N

Nhost 58 Dec 29, 2022
A simple and easy to use Redis client for Dart

redis_dart A simple and minimalist Redis client for Dart See it in pub: https://pub.dev/packages/redis_dart and GitHub: https://github.com/gabrielpach

Gabriel Pacheco 7 Dec 25, 2022
Upper is a open source back-end framework based on the Dart language.

What is Upper? Upper is a open source back-end framework based on the Dart language. With it, it is possible to automatically generate a gRPC API for

Andriws Luna 40 Sep 5, 2022
GChat is a chatting application developed using Flutter(Dart) and firebase for 2 users. Trying to Develop an application that does not sell your data with whatsapp rolling out its privacy policy updates.

Gchat - The Chatting Application A Flutter project for chatting. I used Android Studio and you can you any editor of your choice for ex: VS Code, Inte

Sanchaksh Kaul 6 Nov 6, 2022
a python-like bytes_io implementation for dart

bytes_io A python-like bytes_io implementation for dart A powerful helper for processing raw binary data Usage A simple usage example: import 'package

Kelly 5 Aug 31, 2022
A simple app to keep track the time you Learn, Playing, Reading, ... in every week. This is also my attempt to teach myself Flutter & Dart

Progressor 0.0.1 Sometime you want to set a target for you weekly, for example: "Reading Book for 8 hours every week". This app helps you to do that.

Son Nguyen Hoang 4 Oct 12, 2022
A type-safe command-line parsing library for Dart

plade Plade is a type-safe CLI parsing library for Dart. Highlights Fully type-safe and null-safe. Support for a variety of different parsing styles (

Ryan Gonzalez 6 Jan 1, 2022
Utilities for loading and running WASM modules from Dart code

Provides utilities for loading and running WASM modules Built on top of the Wasmer runtime. Setup Run dart run wasm:setup to build the Wasmer runtime.

Dart 284 Dec 23, 2022
A full, sound, modern and documented JS interop for Dart.

This is (or should be) a full JavaScript interop package using package:js bindings. The bindings are generated by machine-reading WebIDL files for typ

Jonathan Rezende 36 Dec 15, 2022