artemis 5.1.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 92

Artemis

Build dart types from GraphQL schemas and queries

Pub Package GitHub Actions

Check the beta branch for the bleeding edge (and breaking) stuff.

Artemis is a code generator that looks for schema.graphql (GraphQL SDL - Schema Definition Language) and *.graphql files and builds .graphql.dart files typing that query, based on the schema. That's similar to what Apollo does (Artemis is his sister anyway).


Installation #

Add the following to your pubspec.yaml file to be able to do code generation:

dev_dependencies:
  artemis: '>=5.0.0 <6.0.0'
  build_runner: ^1.5.0
  json_serializable: ^3.0.0

The generated code uses the following packages in run-time:

dependencies:
  artemis: '>=5.0.0 <6.0.0' # only if you're using ArtemisClient!
  json_serializable: ^3.0.0
  equatable: ^0.6.1
  meta: '>=1.0.0 <2.0.0' # only if you have non nullable fields
  gql: '>=0.7.3 <1.0.0'

Then run:

pub packages get

or

flutter packages get

Now Artemis will generate the API files for you by running:

pub run build_runner build

or

flutter pub run build_runner build

Configuration #

Artemis offers some configuration options to generate code. All options should be included on build.yaml file on the root of the project:

targets:
  $default:
    builders:
      artemis:
        options:
          # custom configuration options!
OptionDefault valueDescription
generate_helperstrueIf Artemis should generate query/mutation helper GraphQLQuery subclasses.
scalar_mapping[]Mapping of GraphQL and Dart types. See Custom scalars.
schema_mapping[]Mapping of queries and which schemas they will use for code generation. See Schema mapping.
fragments_globnullImport path to the file implementing fragments for all queries mapped in schema_mapping. If it's assigned, fragments defined in schema_mapping will be ignored.

It's important to remember that, by default, build will follow Dart's package layout conventions, meaning that only some folders will be considered to parse the input files. So, if you want to reference files from a folder other than lib/, make sure you've included it on sources:

targets:
  $default:
    sources:
      - lib/**
      - graphql/**
      - data/**
      - schema.graphql

Schema mapping #

By default, Artemis won't generate anything. That's because your queries/mutations should be linked to GraphQL schemas. To configure it, you need to point a schema_mapping to the path of those queries and schemas:

targets:
  $default:
    builders:
      artemis:
        options:
          schema_mapping:
            - output: lib/graphql_api.dart
              schema: lib/my_graphql_schema.graphql
              queries_glob: lib/**.graphql

Each SchemaMap is configured this way:

OptionDefault valueDescription
outputRelative path to output the generated code. It should end with .graphql.dart or else the generator will need to generate one more file.
schemaRelative path to the GraphQL schema.
queries_globGlob that selects all query files to be used with this schema.
type_name_field__typenameThe name of the field used to differentiatiate interfaces and union types (commonly __typename or __resolveType). Note that __typename field are not added automatically to the query. If you want interface/union type resolution, you need to manually add it there.

See examples for more information and configuration options.

Custom scalars #

If your schema uses custom scalars, they must be defined on build.yaml. If it needs a custom parser (to decode from/to json), the custom_parser_import path must be set and the file must implement both fromGraphQL___ToDart___ and fromDart___toGraphQL___ constant functions.

targets:
  $default:
    builders:
      artemis:
        options:
          scalar_mapping:
            - custom_parser_import: 'package:graphbrainz_example/coercers.dart'
              graphql_type: Date
              dart_type: DateTime

If your custom scalar needs to import Dart libraries, you can provide it in the config as well:

targets:
  $default:
    builders:
      artemis:
        options:
          scalar_mapping:
            - custom_parser_import: 'package:graphbrainz_example/coercers.dart'
              graphql_type: BigDecimal
              dart_type:
                name: Decimal
                imports:
                  - 'package:decimal/decimal.dart'

Each ScalarMap is configured this way:

OptionDefault valueDescription
graphql_typeThe GraphQL custom scalar name on schema.
dart_typeThe Dart type this custom scalar should be converted from/to.
custom_parser_importnullImport path to the file implementing coercer functions for custom scalars. See Custom scalars.

See examples for more information and configuration options.

Articles and videos #

  1. Ultimate toolchain to work with GraphQL in Flutter
  2. Awesome GraphQL

ArtemisClient #

If you have generate_helpers, Artemis will create a subclass of GraphQLQuery for you, this class can be used in conjunction with ArtemisClient.

final client = ArtemisClient('/graphql');
final gitHubReposQuery = MyGitHubReposQuery();
final response = await client.execute(gitHubReposQuery);

ArtemisClient adds type-awareness around Link from package:gql/link. You can create ArtemisClient from any Link using ArtemisClient.fromLink.

Check the examples to see how to use it in details.

CHANGELOG #

5.1.0 #

  • Add .graphql. to outputted files path, in a non-breaking change way: a "forwarder" file will be generated to make it retro-compatible when a configurated output doesn't end with .graphql.dart.

5.0.4 #

  • Update CI to include beta branch.

5.0.3 #

  • Update examples to match latest changes.

5.0.2 #

  • Use default names for query/mutation root when SDL does not declare schema.

5.0.1 #

  • Fix generation of recursive input objects introduced by 5.0.0.

5.0.0 #

MAJOR BREAKING CHANGE In this version we moved from json to graphql (SDL) schema parsing. This allowed us to get rid off ±1200 lines of code which makes the
project support much easier. The test files with schema definitions became more clear and human readable.

If you already have your schema in SDL format, just point to it in build.yaml. If not, use this snippet (from this Apollo article) or online helpers like this one to convert from one to another.

4.0.2 #

  • Only add unknownEnumValue on non-list enums
  • Consider all classes to include reference to meta package

4.0.1 #

  • Look at mutation root when generating a mutation

4.0.0 #

MAJOR BREAKING CHANGE This version completely refactors how Artemis generate code (by finally using the implementation of visitor pattern provided by gql). On top of that, I've decided to do other major breaking changes to make code cleaner and more maintainable. Listed:

  • add_query_prefix doesn't exist anymore (it's now the default to generate classes with its "path" from the query), e.g., this query's city field will be typed as CityName$QueryRoot$User$Address$City:
    query city_name {
      user {
        address {
          city {
            name
          }
        }
      }
    }
    
    This change was also done to tip users to NOT use those generated queries directly on their code, to avoid coupling them to your business logic.
  • custom_parser_import was moved to inside a ScalarMap, and use_custom_parser was removed.
  • resolve_type_field option was renamed to type_name_field, as __typename is the correct field name (by GraphQL spec).
  • Classes generated for mutation will have a Mutation suffix, as queries already have Query suffix.
  • Change pre-generation data classes constructors to named parameters, so if you're using GraphQLQueryBuilder.onBuild, it will break.

And also:

  • Add more logs and errors while generating code, to help debugging.
  • Add more/refactor tests.
  • Add a GitHub example.

TODO:

  • [ ] re-add more logs
  • [ ] clean options (?)
  • [ ] prefix every class with $ (?)
  • [ ] refactor class naming variables
  • [ ] review readme and changelog

3.2.1 #

  • Fix unknown enum: add prefix

3.2.0 #

  • Make enums loose. When unknown values are provided into an enum, it will fall back to a custom ARTEMIS_UNKNOWN value avoiding breaking/crashing the client.

3.1.0 #

  • Allow to dispose ArtemisClient underlining http client when possible

3.0.0 #

  • BREAKING: Marks non nullable input field as @required #68

2.2.2 #

  • Make lists as input objects work again

2.2.1 #

  • Display error on types not found on schema

2.2.0+1 #

  • Add "Articles and videos" category on README

2.2.0 #

  • Share fragments between queries and schemas (see fragments_glob) #65

2.1.4 #

  • Add missing prefix to generated enums

2.1.3 #

  • Bump equatable/gql suite, refine GitHub actions

2.1.2 #

  • Bump json_serializable/json_annotation

2.1.1 #

  • Properly consider Union types on generation

2.1.0+1 #

  • Fix GitHub actions deploy pipeline
  • Make sure artemis depends on json_annotation

2.1.0 #

  • Generate fragments as mixins

2.0.7+1 #

  • README updates

2.0.7 #

  • Add missing prefix to interfaces

2.0.6 #

  • Perserve the query name casing

2.0.5 #

  • Bump gql package

2.0.4 #

  • Bump gql package

2.0.3 #

  • Generate every field of input objects

2.0.2 #

  • Support __schema key under the data field or on root of schema.json.

2.0.1 #

  • Loosen up dependencies to make it work again with Flutter beta channel

2.0.0 #

  • BREAKING: move GraphQLError to package:gql. If you don't use it, or just reference it indirectly, it will not be breaking, but a major will be bumped anyway, just for sure.
  • Upgrade package:gql to version 0.7.4
  • Build GQL AST into generated Dart code instead of the raw string
  • Use Link from package:gql/link as the execution interface of ArtemisClient
  • Use package:gql_dedupe_link and package:gql_http_link as the default links

1.0.4 #

  • Add a test to guarantee query inputs can be lists

1.0.3 #

  • Disable implicit casts
  • Avoid double-parsing the source string

1.0.2 #

  • Differentiate lists from named types when looping through variables
  • Consider nullable operation name when defining query name

1.0.1 #

  • Upgrade gql to version 0.2.0 to get rid of direct dependency on source_span and for better parsing errors.
  • Filter for SchemaMap with output when generating code

1.0.0 #

  • Breaking: Add required output option to SchemaMap
  • Make Artemis a $lib$ synthetic generator
  • Add add_query_prefix option to SchemaMap

0.7.0 #

  • Make generated classes a mixin of Equatable, meaning they can be easily comparable with ==

0.6.1 #

  • Include pubspec.lock files of examples

0.6.0 #

  • Replace graphql_parser with gql package

0.5.1 #

  • Add most documentation
  • Increase pana grade (health and maintenance)
  • Fix some stuff related to importing http on client

0.5.0 #

  • Start using code_builder to better generate Dart code

0.4.0 #

  • Allow scalar mappings to include imports for types

0.3.2 #

  • Decode HTTP response as UTF-8 on execute helper.

0.3.1 #

  • Export common used files on default package route (package:artemis/artemis.dart)
  • Use single schemaMap globbing stream to make sure only one schema will be found
  • Add missing changelog
  • Test new github actions

0.3.0 BREAKING #

  • Add new generators to GraphQLQuery and QueryArguments
  • Fix toJson() on JsonSerializable classes (for nested entities)
  • [BREAKING] Remove the execute* functions generations, to use instead the generic ArtemisClient class that should receive a GraphQLQuery generated subclass.

0.2.1 #

Set HTTP headers only when using default HTTP client.

0.2.0 BREAKING #

Completely overhaul how this works.

Artemis won't generate a full schema typing anymore. Instead, it will use the schema to generate typings from a specific query or mutation. It will also create helper functions to execute those queries. See README for more info.

This is totally a breaking change but as this library is still on alpha, I should keep it under 1.0.

0.1.3 #

  • Make objects that implement interfaces override resolveType

0.1.2 #

  • Improve package score

0.1.1 #

  • Enable tests on pipeline

0.1.0 #

  • "Fix" json_serializable dependency
  • Add tests
  • Generate union types as inheritance
  • Generate interface types as implementation
  • Make generated code choose inheritance

0.0.1 #

  • First release
  • No tests
  • No documentation
  • Parse complex GraphQL schemas (incorrectly, now I know)
  • Parse all GraphQL types types (union, interface, enum, input object, object, scalar, list, non null)
  • Consider custom scalars
  • Not even compile from scratch
  • Lot of bugs

example/README.md

Examples #

This folder contains some examples on how to use artemis.

pokemon #

A simple example, showing Pokémon GraphQL schema generation.

graphqbrainz #

A more complex example, for graphbrainz (a MusicBrainz GraphQL server). Featuring union types, interfaces and custom scalars.

github #

Even simpler example, for GitHub GraphQL API. I didn't commit the schema because it's too big (~3MB), so provide your own if you're running the example: https://github.com/octokit/graphql-schema

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  artemis: ^5.1.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:artemis/artemis.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
87
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
92
Learn more about scoring.

We analyzed this package on Mar 31, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6

Maintenance issues and suggestions

Support latest dependencies. (-10 points)

The version constraint in pubspec.yaml does not support the latest published versions for 1 dependency (recase).

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.6.0 <3.0.0
build ^1.1.4 1.2.2
build_config ^0.4.0 0.4.2
code_builder ^3.2.0 3.2.1
equatable ^1.0.1 1.1.1
gql ^0.12.2 0.12.2
gql_code_gen ^0.1.5 0.1.5 0.2.0-alpha.1
gql_dedupe_link ^1.0.9 1.0.9
gql_exec ^0.2.2 0.2.2
gql_http_link ^0.2.7 0.2.7
gql_link ^0.2.3 0.2.3
http ^0.12.0+2 0.12.0+4
json_annotation ^3.0.0 3.0.1
meta ^1.1.7 1.1.8
path ^1.6.2 1.6.4
recase ^2.0.1 2.0.1 3.0.0
source_gen ^0.9.4+2 0.9.5
Transitive dependencies
_fe_analyzer_shared 1.0.3
analyzer 0.39.4
async 2.4.1
built_collection 4.3.2
built_value 7.0.9
charcode 1.1.3
checked_yaml 1.0.2
collection 1.14.12
convert 2.1.1
crypto 2.1.4
csslib 0.16.1
dart_style 1.3.3
fixnum 0.10.11
glob 1.2.0
html 0.14.0+3
http_parser 3.1.4
js 0.6.1+1
matcher 0.12.6
node_interop 1.0.3
node_io 1.0.1+2
package_config 1.9.3
pub_semver 1.4.4
pubspec_parse 0.1.5
quiver 2.1.3
source_span 1.7.0
stack_trace 1.9.3
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
watcher 0.9.7+14
yaml 2.2.0
Dev dependencies
args ^1.5.2 1.6.0
build_runner ^1.5.0
build_test ^0.10.7+3
json_serializable ^3.0.0
logging ^0.11.4 0.11.4
pedantic ^1.8.0+1 1.9.0
test ^1.6.3