Code Monkey home page Code Monkey logo

artemis's People

Contributors

amadeu01 avatar budde377 avatar comigor avatar jeffscaturro-aka avatar jmoseley avatar klavs avatar lasserosenow avatar leoiacovini avatar marcelotheodoro avatar matthiasng avatar mattisbrizard avatar minhthong095 avatar miorimmax avatar oakesja avatar pd4d10 avatar tuannyharumi avatar vasilich6107 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

artemis's Issues

Cannot process queries with non-scalar inputs

It seems like queries with Object inputs can't be processed. I'm getting the following error for the following query:

query SomeQuery($filter: ModelEventFilterInput) {
    viewer {
        __typename
        id
    }
}
[INFO] Generating build script...
[INFO] Generating build script completed, took 307ms

[INFO] BuildDefinition:Initializing inputs
[INFO] BuildDefinition:Reading cached asset graph...
[INFO] BuildDefinition:Reading cached asset graph completed, took 101ms

[INFO] BuildDefinition:Checking for updates since last build...
[INFO] BuildDefinition:Checking for updates since last build completed, took 738ms

[INFO] Build:Running build...
[INFO] Build:Running build completed, took 29ms

[INFO] Build:Caching finalized dependency graph...
[INFO] Build:Caching finalized dependency graph completed, took 55ms

[SEVERE] artemis:artemis on lib/$lib$ (cached):

Stack Overflow
dart:core                                             Iterable.firstWhere
package:artemis/generator/graphql_helpers.dart 53:10  getSingleScalarMap
package:artemis/generator/graphql_helpers.dart 33:22  buildTypeString
package:artemis/generator.dart 173:23                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
.                                                     ...
.                                                     ...
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 289:13                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 179:20                 _createClassProperty
package:artemis/generator.dart 279:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 303:8                  _extractClasses
package:artemis/generator.dart 106:30                 generateQuery.<fn>
dart:core                                             List.forEach
package:artemis/generator.dart 100:35                 generateQuery
package:artemis/generator.dart 21:21                  generateLibrary.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 23:8                   generateLibrary
package:artemis/builder.dart 93:29                    GraphQLQueryBuilder.build

[SEVERE] Build:
Failed after 131ms

Is there something that would need to be set explicitly for this to work?

Missing enum type when create .dart file

I create by file graphql with content:

query AllUsers($filter: FilterInput, $limit: Int, $nextToken: String) {
  allUsers(filter: $filter, limit: $limit, nextToken: $nextToken) {
    items {
      Attributes {
        Name
        Value
      }
      Username
    }
    nextToken
  }
}

with file schema.json create from appsync aws. Everything worked fine and created .dart files but it didn't include enum type.

Has it been supported since the beginning or is this a bug?

Create one file for each query when using wildcards on queries_glob

I have this on my build.yaml

      schema_mapping:
        - schema: rygapp.schema.json
          queries_glob: graphql/**.query.graphql
          output: lib/graphql/consultas.dart

When I run I received this error :

Exception: Two classes were generated with the same name Usuario!
You may want to do either:

  • Enable add_query_prefix on this schema_map

  • Make queries_glob stricter, to gather less .graphql files on a single output

  • Use alias on one of the places a Usuario field is requested

    Ok. I understand what causes the issue.

What about create one file per query :

      schema_mapping:
        - schema: rygapp.schema.json
          queries_glob: graphql/**.query.graphql
          output: lib/graphql/**

So it will create many files without the need to declare each query on build.yaml

Are subscriptions supported?

Hey there, tried searching but couldn't find any mention of subscription query types for gql. Wondering if they are currently supported and if not if there is any plan to support them?

thanks!

Enum type names have funky names

I have the following mutation written in a file that is built by artemis:

mutation ExternalAuthenticate(
    $provider: AuthProvider!
    $email: String!
    $username: String!
) {
    externalAuthenticate(
        provider: $provider
        email: $email
        username: $username
    )
}

AuthProvider is an enum, and works perfectly in, say, the GraphQL Playground. However, the artemis generated output does not contain this enum type. I get an error in the output, for the variable arguments of the mutation that tells me the class is undefined.

@JsonSerializable(explicitToJson: true)
class ExternalAuthenticateArguments extends JsonSerializable with EquatableMixin {
  ExternalAuthenticateArguments({this.provider, this.email, this.username});

  factory ExternalAuthenticateArguments.fromJson(Map<String, dynamic> json) =>
      _$ExternalAuthenticateArgumentsFromJson(json);

  final AuthProvider provider; // Undefined class 'AuthProvider'.

  final String email;

  final String username;

  @override
  List<Object> get props => [provider, email, username];
  Map<String, dynamic> toJson() => _$ExternalAuthenticateArgumentsToJson(this);
}

Here is my build.yaml:

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

[feature request] Mark arguments as @required if they have an exclamation mark(non nullable)

Hi. Thanks for you work.
I'd like to suggest an improvement.

I have a query

query SearchDestinationsData($pagination: PaginationInput!, $startsWith: Boolean!, $term: String!, $types: [DestinationType!]) {
    searchDestinations(pagination: $pagination, startsWith: $startsWith, term: $term, types: $types) {
        destinations {
            id
            name
            type
        }
        totalCount
    }
}

After generation I have corresponding class

class SearchDestinationsDataArguments extends JsonSerializable
    with EquatableMixin {
  SearchDestinationsDataArguments(
      {this.pagination, this.startsWith, this.term, this.types});

  ...
}

The arguments in constructor are not marked with @required annotation but they are definitely required according(marked with exclamation mark PaginationInput!) to the schema definition.

Expected result

SearchDestinationsDataArguments(
      {@required this.pagination, @required this.startsWith, @required this.term, this.types})

This will help to avoid unexpected errors.
Thanks

Using third party types on custom scalars

Hey there! I'm exploring this library a bit, working good so far, but I got a custom scalar for BigDecimal that uses decimal on the dart side, as you can see in my custom parser:

import 'package:decimal/decimal.dart';

Decimal fromGraphQLBigDecimalToDartDecimal(String value) => Decimal.parse(value);

String fromDartDecimalToGraphQLBigDecimal(Decimal value) => value.toString();

But the generated code does not build because it is missing a import for package:decimal/decimal.dart, so the compiler cannot figure out where Decimal is defined.

I'm editing the generated file and adding the import manually in order to be able to run my app.

Maybe we should have a imports array in the ScalarMap and inject the imports from there in the resulting file?

The build config would look like this:

scalar_mapping:
  - graphql_type: BigDecimal
    dart_type: Decimal
    use_custom_parser: true
    imports: ['package:decimal/decimal.dart']

Another alternative I can think of is using a map, but that could make the logic a bit more complicated (to handle string or map):

scalar_mapping:
  - graphql_type: BigDecimal
    dart_type:
      name: Decimal
      import: 'package:decimal/decimal.dart'
    use_custom_parser: true

WDYT? I can work on a PR to implement this on my spare time.

Possible to generate schema types?

Is there a way to generate classes from the base types of a schema? Is this planned?

We'll want to do this for graphql-flutter, and maintain fragment inheritance somehow

Maybe something like this: https://gist.github.com/micimize/ec9df3c1df23f415621fd3da7e81209e
// base type
class Foo {
  String _foo;
  int _bar;
}

//fragment exposing foo
class FooFragment extends Foo {
  String get foo => _foo;
  set foo(String value) => _foo = value;

  FooFragment({String foo}) {
    this.foo = foo;
  }
}

Relatedly, we'll need to be able to customize the generated models if we continue with the moor cache route

Ignore analyzer rules on generated files

Hi,

Generated files are not following some analyzer rules (ex: public_member_api_docs), would it be possible to add an //ignore_for_file: .. with rules ?

Or even better, as possible with json_serializable (coming from source_gen: https://pub.dev/packages/source_gen#configuring-combining_builder-ignore_for_file) a way to specify in bulid.yaml; some rules to ignore in generated files.

source_gen|combining_builder:
        options:
          ignore_for_file:
            - public_member_api_docs

Thanks :)

Support grahphql codegen introspection schemas

When using graphql codegen and the introspection plugin, the JSON output has a root key of schema, but the artemis parser expects this object to be nested inside a root data object (I believe this is the result if you request the introspection schema from the server).

The error you see in my case is:

[SEVERE] artemis:artemis on lib/$lib$:

NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: []("__schema")

It shouldn't be too hard to support both formats in the parser.

An alternative solution might be to support fetching the schema from a server directly (similar to what is supported by graphql codegen). I am already using graphql codegen for another corner of this project, so it was convenient to use it for providing the introspection json for artemis to consume as well, but it would be much cleaner to configure artemis to fetch the schema from the server directly.

Could not generate dart file from query.

I'm getting this error.
Not sure what could cause that

NoSuchMethodError: The getter 'value' was called on null.
Receiver: null
Tried calling: value
dart:core                                                               Object.noSuchMethod
package:artemis/generator.dart 71:43                                    generateQuery
package:artemis/generator.dart 33:19                                    generateLibrary.<fn>
dart:_internal                                                          ListIterable.toList
package:artemis/generator.dart 34:8                                     generateLibrary
package:artemis/builder.dart 66:29                                      GraphQLQueryBuilder.build
package:build                                                           runBuilder
package:build_runner_core/src/generate/build_impl.dart 472:19           _SingleBuild._runForInput.<fn>.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 300:15  _NoOpBuilderActionTracker.trackStage
package:build_runner_core/src/generate/build_impl.dart 470:23           _SingleBuild._runForInput.<fn>.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 429:22           _SingleBuild._runForInput.<fn>
package:pool/pool.dart 127:28                                           Pool.withResource
package:build_runner_core/src/generate/build_impl.dart 425:17           _SingleBuild._runForInput
package:build_runner_core/src/generate/build_impl.dart 373:38           _SingleBuild._runBuilder.<fn>
dart:async                                                              Future.wait
package:build_runner_core/src/generate/build_impl.dart 372:36           _SingleBuild._runBuilder
package:build_runner_core/src/generate/build_impl.dart 319:20           _SingleBuild._runPhases.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 184:15  _NoOpBuildPerformanceTracker.trackBuildPhase
package:build_runner_core/src/generate/build_impl.dart 315:47           _SingleBuild._runPhases.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 309:32           _SingleBuild._runPhases
package:build_runner_core/src/logging/logging.dart 25:30                logTimedAsync
package:build_runner_core/src/generate/build_impl.dart 266:26           _SingleBuild._safeBuild.<fn>
dart:async                                                              runZoned
package:build_runner_core/src/generate/build_impl.dart 261:5            _SingleBuild._safeBuild
package:build_runner_core/src/generate/build_impl.dart 208:24           _SingleBuild.run
package:build_runner_core/src/generate/build_impl.dart 96:42            BuildImpl.run
package:build_runner_core/src/generate/build_runner.dart 25:14          BuildRunner.run
package:build_runner                                                    BuildCommand.run
package:args/command_runner.dart 197:27                                 CommandRunner.runCommand
package:args/command_runner.dart 112:25                                 CommandRunner.run.<fn>
dart:async                                                              new Future.sync
package:args/command_runner.dart 112:14                                 CommandRunner.run
package:build_runner                                                    run
.dart_tool/build/entrypoint/build.dart 27:22                            main

I also notice that it printed a lot of this warnnings

[INFO] Build:Running build...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "id" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "role" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "last_updated_by_card" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "opened_cards_count" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "anyone_can_create_card" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "users_count" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "id" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "role" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "last_updated_by_card" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "opened_cards_count" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "anyone_can_create_card" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "users_count" of class "Repo". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "id" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "name" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "icon" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "role" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "opened_cards_count" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "id" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "name" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "icon" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "role" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "opened_cards_count" of class "PublicPipeInterface". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "name" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "icon" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "last_updated_by_card" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "anyone_can_create_card" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "users_count" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "name" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "icon" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "last_updated_by_card" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "anyone_can_create_card" of class "PipeSharedProperties". Moving on...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "users_count" of class "PipeSharedProperties". Moving on...
[SEVERE] artemis:artemis on lib/$lib$:

[Not sure what broken] Unable to generate code

I'm not sure what has broken here.

It might have something to do with _defaultScalarMapping, or some sort of variable that should be specified in the ScalarMap, but the error is not clear, so I couldn't know what I'm doing wrong or if it is a new bug.

ScalarMap getSingleScalarMap(GeneratorOptions options, GraphQLType type) =>
options.scalarMapping
.followedBy(_defaultScalarMapping)
.firstWhere((m) => m.graphQLType == type.name,
orElse: () => ScalarMap(
graphQLType: type.name,
dartType: DartType(name: type.name),
));

Stack Overflow
dart:collection                                       ListMixin.followedBy
package:artemis/generator/graphql_helpers.dart 49:10  getSingleScalarMap
package:artemis/generator/graphql_helpers.dart 30:22  buildTypeString
package:artemis/generator/graphql_helpers.dart 27:14  buildTypeString
package:artemis/generator.dart 155:23                 _createClassProperty
package:artemis/generator.dart 238:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 264:8                  _extractClasses
package:artemis/generator.dart 249:15                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 160:20                 _createClassProperty
package:artemis/generator.dart 238:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 264:8                  _extractClasses
package:artemis/generator.dart 249:15                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 160:20                 _createClassProperty
package:artemis/generator.dart 238:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 264:8                  _extractClasses
package:artemis/generator.dart 249:15                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 160:20                 _createClassProperty
package:artemis/generator.dart 238:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 264:8                  _extractClasses
package:artemis/generator.dart 249:15                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 160:20                 _createClassProperty
package:artemis/generator.dart 238:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
.                                                     ...
.                                                     ...
package:artemis/generator.dart 264:8                  _extractClasses
package:artemis/generator.dart 249:15                 _extractClasses.<fn>.<fn>
package:artemis/generator.dart 160:20                 _createClassProperty
package:artemis/generator.dart 238:14                 _extractClasses.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 264:8                  _extractClasses
package:artemis/generator.dart 88:30                  generateQuery.<fn>
dart:core                                             List.forEach
package:artemis/generator.dart 82:35                  generateQuery
package:artemis/generator.dart 21:19                  generateLibrary.<fn>
dart:_internal                                        ListIterable.toList
package:artemis/generator.dart 22:8                   generateLibrary
package:artemis/builder.dart 66:29                    GraphQLQueryBuilder.build


[SEVERE] Build:
Failed after 8.4s
pub finished with exit code 1

#0      throwToolExit (package:flutter_tools/src/base/common.dart:28:3)
#1      pubInteractively (package:flutter_tools/src/dart/pub.dart:213:5)
<asynchronous suspension>
#2      PackagesForwardCommand.runCommand (package:flutter_tools/src/commands/packages.dart:241:11)
<asynchronous suspension>
#3      FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:527:18)
#4      _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:71:64)
#5      _rootRunUnary (dart:async/zone.dart:1132:38)
#6      _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#7      _FutureListener.handleValue (dart:async/future_impl.dart:137:18)
#8      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45)
#9      Future._propagateToListeners (dart:async/future_impl.dart:707:32)
#10     Future._completeWithValue (dart:async/future_impl.dart:522:5)
#11     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:552:7)
#12     _rootRun (dart:async/zone.dart:1124:13)
#13     _CustomZone.run (dart:async/zone.dart:1021:19)
#14     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
#15     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
#16     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#17     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#18     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:116:13)
#19     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:173:5)

Automatic insertion of __typename field to unions/interfaces selection set

Artemis needs the value of __typename field of union types and interfaces to be able to differentiate the object type when resolving those types. This means the user must add the type name field (tipically __typename) to the union type/interfaces they're querying.

Ideally, Artemis could automatically add this field to the query, avoiding this hassle.

Specify casing for generated Dart class names and properties

I'm working with a graphql endpoint that has both class names and property names come back in snake_case. This causes issues with Dart linter/compiler since it is expecting class names to be in PascalCase and properties to be in camelCase

Currently functionality generates as

@JsonSerializable(explicitToJson: true)
class group_mutation_response with EquatableMixin {
  group_mutation_response({this.returning_groups});

  factory group_mutation_response.fromJson(Map<String, dynamic> json) =>
      _$group_mutation_responseFromJson(json);

  List<group> returning_groups;

  @override
  List<Object> get props => [returning_groups];
  Map<String, dynamic> toJson() => _$group_mutation_responseToJson(this);
}

Ideally it would generate as

@JsonSerializable(explicitToJson: true)
class GroupMutationResponse with EquatableMixin {          // <----- PascalCase
  GroupMutationResponse({this.returningGroups});

  factory GroupMutationResponse.fromJson(Map<String, dynamic> json) =>
      _$GroupMutationResponse(json);

  @JsonKey(name: 'returning_groups')  //  <---- Handle mapping to/from graphql json
  List<Group> returningGroups;  // <---- camelCase

  @override
  List<Object> get props => [returningGroups];
  Map<String, dynamic> toJson() => _$GroupMutationResponseToJson(this);  //  <---- PascalCase
}

Is there anything I can do to force the casing to generate using dart compatible casing?

generate single mixin for fragment

#52 Issue with shared fragments is partially resolved in this PR: #65

But there is still a problem, new fragment mixin is generated for every query.
So you must use different output files for queries which use the same fragment.
This leading to the next problem: you can't use these mixins as base class for your fields in generated classes.

I hope the most appropriate solution would be to add fragmets_output field in build.yaml options and import this in queries output. (maybe also export(?))

Complex input will generate wrong argument type

I have tried to generate the error using the pokemon example from the this repo.
the schema:
https://github.com/agent3bood/artemis/blob/master/example/pokemon/pokemon.schema.graphql#L96
the query:
https://github.com/agent3bood/artemis/blob/master/example/pokemon/graphql/complex_query.query.graphql
the generated input type is wrong:
https://github.com/agent3bood/artemis/blob/master/example/pokemon/lib/graphql/complex_query.graphql.dart#L59
it is
final List<ComplexQuery$Query> input;
which should be
final List<ComplexQuery$complexObjects> input;

Connections and Unions

Hey there! First of all thanks for this package, it really helps us to improve our development process! I have some troubles building unions and connections with unions.

I have the following gql queries:

query Search($searchTerm, $filters, $first, $last, and more...) {
  edges {
    node {
      .. on Product {
        id
      }
      .. on User {
        id
      }
    }
  }
}

or

query CurrentViewer($id, $favorites_first, and more..) {
  node(id: $id) {
    id
    favorites(first: $favorites_first) {
      edges {
        node {
          .. on Location {
            id
          }
          .. on Category {
            id
          }
        }
      }
    } 
  }
}

In both cases the type Node has no props e.g.:

--- SNIP ---
@JsonSerializable(explicitToJson: true)
class Searchables with EquatableMixin {
  Searchables();

  factory Searchables.fromJson(Map<String, dynamic> json) =>
      _$SearchablesFromJson(json);

  @override
  List<Object> get props => []; # empty props 
  Map<String, dynamic> toJson() => _$SearchablesToJson(this);
}
--- SNIP ---

Expectation is:

--- SNIP ---
@JsonSerializable(explicitToJson: true)
class Node with EquatableMixin {
  Node();

  factory Node.fromJson(Map<String, dynamic> json) {
    switch (json['__typename']) {
      case 'Category':
        return Category.fromJson(json);
      case 'Location':
        return Location.fromJson(json);
      default:
    }
    return _$NodeFromJson(json);
  }
}
--- SNIP ---

Failing file name in debugging output

Including the file name in the stack trace output would greatly improve usability

flutter pub run build_runner build -vvv
[INFO] Generating build script...
[INFO] Generating build script completed, took 267ms

[INFO] BuildDefinition:Initializing inputs
[INFO] BuildDefinition:Reading cached asset graph...
[INFO] BuildDefinition:Reading cached asset graph completed, took 94ms

[INFO] BuildDefinition:Checking for updates since last build...
[INFO] BuildDefinition:Checking for updates since last build completed, took 837ms

[INFO] Build:Running build...
[INFO] Build:Running build completed, took 27ms

[INFO] Build:Caching finalized dependency graph...
[INFO] Build:Caching finalized dependency graph completed, took 53ms

[SEVERE] artemis:artemis on lib/$lib$ (cached):

NoSuchMethodError: The getter 'selections' was called on null.
Receiver: null
Tried calling: selections
dart:core                                                               Object.noSuchMethod
package:artemis/generator.dart 435:28                                   _extractClasses.<fn>
dart:collection                                                         SetMixin.forEach
package:artemis/generator.dart 423:23                                   _extractClasses
package:artemis/generator.dart 99:19                                    generateQuery
package:artemis/generator.dart 21:21                                    generateLibrary.<fn>
dart:_internal                                                          ListIterable.toList
package:artemis/generator.dart 22:8                                     generateLibrary
package:artemis/builder.dart 75:29                                      GraphQLQueryBuilder.build
package:build                                                           runBuilder
package:build_runner_core/src/generate/build_impl.dart 478:19           _SingleBuild._runForInput.<fn>.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 300:15  _NoOpBuilderActionTracker.trackStage
package:build_runner_core/src/generate/build_impl.dart 476:23           _SingleBuild._runForInput.<fn>.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 434:22           _SingleBuild._runForInput.<fn>
package:pool/pool.dart 127:28                                           Pool.withResource
package:build_runner_core/src/generate/build_impl.dart 430:17           _SingleBuild._runForInput
package:build_runner_core/src/generate/build_impl.dart 378:38           _SingleBuild._runBuilder.<fn>
dart:async                                                              Future.wait
package:build_runner_core/src/generate/build_impl.dart 377:36           _SingleBuild._runBuilder
package:build_runner_core/src/generate/build_impl.dart 323:20           _SingleBuild._runPhases.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 184:15  _NoOpBuildPerformanceTracker.trackBuildPhase
package:build_runner_core/src/generate/build_impl.dart 319:47           _SingleBuild._runPhases.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 313:32           _SingleBuild._runPhases
package:build_runner_core/src/logging/logging.dart 25:30                logTimedAsync
package:build_runner_core/src/generate/build_impl.dart 270:26           _SingleBuild._safeBuild.<fn>
dart:async                                                              runZoned
package:build_runner_core/src/generate/build_impl.dart 265:5            _SingleBuild._safeBuild
package:build_runner_core/src/generate/build_impl.dart 212:24           _SingleBuild.run
package:build_runner_core/src/generate/build_impl.dart 97:56            BuildImpl.run
package:build_runner_core/src/generate/build_runner.dart 25:14          BuildRunner.run
package:build_runner                                                    BuildCommand.run
package:args/command_runner.dart 197:27                                 CommandRunner.runCommand
package:args/command_runner.dart 112:25                                 CommandRunner.run.<fn>
dart:async                                                              new Future.sync
package:args/command_runner.dart 112:14                                 CommandRunner.run
package:build_runner                                                    run
.dart_tool/build/entrypoint/build.dart 31:22                            main

[SEVERE] Build:
Failed after 145ms
pub finished with exit code 1

'ListTypeNode' is not a subtype of type 'NamedTypeNode'

It might be related to

final List<QueryInput> inputs = [];
final List<Definition> inputsClasses = [];
if (operation.variableDefinitions != null) {
operation.variableDefinitions.forEach((v) {
NamedTypeNode unwrappedType = v.type;
if (v.type is ListTypeNode) {
unwrappedType = (v.type as ListTypeNode).type;
}

type 'ListTypeNode' is not a subtype of type 'NamedTypeNode'
package:artemis/generator.dart 84:21                                    generateQuery.<fn>
dart:core                                                               List.forEach
package:artemis/generator.dart 83:35                                    generateQuery
package:artemis/generator.dart 33:19                                    generateLibrary.<fn>
dart:_internal                                                          ListIterable.toList
package:artemis/generator.dart 34:8                                     generateLibrary
package:artemis/builder.dart 66:29                                      GraphQLQueryBuilder.build
package:build                                                           runBuilder
package:build_runner_core/src/generate/build_impl.dart 477:19           _SingleBuild._runForInput.<fn>.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 300:15  _NoOpBuilderActionTracker.trackStage
package:build_runner_core/src/generate/build_impl.dart 475:23           _SingleBuild._runForInput.<fn>.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 434:22           _SingleBuild._runForInput.<fn>
package:pool/pool.dart 127:28                                           Pool.withResource
package:build_runner_core/src/generate/build_impl.dart 430:17           _SingleBuild._runForInput
package:build_runner_core/src/generate/build_impl.dart 378:38           _SingleBuild._runBuilder.<fn>
dart:async                                                              Future.wait
package:build_runner_core/src/generate/build_impl.dart 377:36           _SingleBuild._runBuilder
package:build_runner_core/src/generate/build_impl.dart 323:20           _SingleBuild._runPhases.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 184:15  _NoOpBuildPerformanceTracker.trackBuildPhase
package:build_runner_core/src/generate/build_impl.dart 319:47           _SingleBuild._runPhases.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 313:32           _SingleBuild._runPhases
package:build_runner_core/src/logging/logging.dart 25:30                logTimedAsync
package:build_runner_core/src/generate/build_impl.dart 270:26           _SingleBuild._safeBuild.<fn>
dart:async                                                              runZoned
package:build_runner_core/src/generate/build_impl.dart 265:5            _SingleBuild._safeBuild
package:build_runner_core/src/generate/build_impl.dart 212:24           _SingleBuild.run
package:build_runner_core/src/generate/build_impl.dart 97:56            BuildImpl.run
package:build_runner_core/src/generate/build_runner.dart 25:14          BuildRunner.run
package:build_runner                                                    BuildCommand.run
package:args/command_runner.dart 197:27                                 CommandRunner.runCommand
package:args/command_runner.dart 112:25                                 CommandRunner.run.<fn>
dart:async                                                              new Future.sync
package:args/command_runner.dart 112:14                                 CommandRunner.run
package:build_runner                                                    run
.dart_tool/build/entrypoint/build.dart 27:22                            main

Sharing fragments between queries

Is it possible to share fragments between queries?

For example if I have a fragment and two queries that use it...

fragment Category on JobCategory {
  id
  name
}
query fetchInformationToCreateJobs($divisionId: Int!) {
  jobCategories(divisionId: $divisionId) {
    ...JobCategory
  }
}
query prefetcher($divisionId: Int!) {
  jobCategories(divisionId: $divisionId) {
    ...JobCategory
  }
  division(id: $divisionId) {
     id 
     name
  }
}

If I place the fragment one of the queries or the other I get the following error message:

[SEVERE] artemis:artemis on lib/$lib$:

Bad state: No element
dart:collection                                                         ListMixin.firstWhere
package:artemis/generator.dart 290:16                                   _extractClasses.<fn>
dart:core                                                               Iterable.forEach
package:artemis/generator.dart 306:10                                   _extractClasses
package:artemis/generator.dart 320:15                                   _extractClasses.<fn>.<fn>
package:artemis/generator.dart 159:20                                   _createClassProperty
package:artemis/generator.dart 206:10                                   _selectionToClassProperty
package:artemis/generator.dart 308:20                                   _extractClasses.<fn>
dart:core                                                               Iterable.forEach
package:artemis/generator.dart 306:10                                   _extractClasses
package:artemis/generator.dart 98:19                                    generateQuery
package:artemis/generator.dart 21:21                                    generateLibrary.<fn>
dart:_internal                                                          ListIterable.toList
package:artemis/generator.dart 22:8                                     generateLibrary
package:artemis/builder.dart 75:29                                      GraphQLQueryBuilder.build
package:build                                                           runBuilder
package:build_runner_core/src/generate/build_impl.dart 478:19           _SingleBuild._runForInput.<fn>.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 300:15  _NoOpBuilderActionTracker.trackStage
package:build_runner_core/src/generate/build_impl.dart 476:23           _SingleBuild._runForInput.<fn>.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 434:22           _SingleBuild._runForInput.<fn>
package:pool/pool.dart 127:28                                           Pool.withResource
package:build_runner_core/src/generate/build_impl.dart 430:17           _SingleBuild._runForInput
package:build_runner_core/src/generate/build_impl.dart 378:38           _SingleBuild._runBuilder.<fn>
dart:async                                                              Future.wait
package:build_runner_core/src/generate/build_impl.dart 377:36           _SingleBuild._runBuilder
package:build_runner_core/src/generate/build_impl.dart 323:20           _SingleBuild._runPhases.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 184:15  _NoOpBuildPerformanceTracker.trackBuildPhase
package:build_runner_core/src/generate/build_impl.dart 319:47           _SingleBuild._runPhases.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 313:32           _SingleBuild._runPhases
package:build_runner_core/src/logging/logging.dart 25:30                logTimedAsync
package:build_runner_core/src/generate/build_impl.dart 270:26           _SingleBuild._safeBuild.<fn>
dart:async                                                              runZoned
package:build_runner_core/src/generate/build_impl.dart 265:5            _SingleBuild._safeBuild
package:build_runner_core/src/generate/build_impl.dart 212:24           _SingleBuild.run
package:build_runner_core/src/generate/build_impl.dart 97:56            BuildImpl.run
package:build_runner_core/src/generate/build_runner.dart 25:14          BuildRunner.run
package:build_runner                                                    BuildCommand.run
package:args/command_runner.dart 197:27                                 CommandRunner.runCommand
package:args/command_runner.dart 112:25                                 CommandRunner.run.<fn>
dart:async                                                              new Future.sync
package:args/command_runner.dart 112:14                                 CommandRunner.run
package:build_runner                                                    run
.dart_tool/build/entrypoint/build.dart 31:22                            main

If I place the fragment in both of the queries I get:

Exception: Two classes were generated with the same name `JobCategory`!
You may want to do either:
- Enable add_query_prefix on this schema_map
- Make queries_glob stricter, to gather less .graphql files on a single output
- Use alias on one of the places a `JobCategory` field is requested

I understand that it is possible to define two different schema mappings and have these generate to two different files. However, I would like the resultant fragment class to be independent of the queries like apollo does

Generate queries in the background based on usage

For javascript there is a module called gqless: https://gqless.dev/

It basically generates all your queries etc. based on how you use them in your code. So you don't need any .query.graqhql files anymore and you also don't need to update them because you need a new property in your request somewhere within your app.

But you still get auto completion because gqless uses the schema.graphl file to generate the types for that.

So I think that this approach is pretty cool as you will automatically fetch the most minimal amount of data from your server as possible, because your code defines, what you need and you don't fetch to much just because you put to much fields into your local .query.graphql file..
Also the general usage is much faster as you don't need to write those files anymore at all.

So I think it would be amazing to have such a feature in Artemis.
What do you think?

Make enums loose

Today, it's always a breaking change to add a new option on a Enum on Artemis: the generated code will create an Enum based on the schema of on that code was generated, and if the server returns a new value on that enum, it will break with "ArgumentError".

To make enums retro-compatible, I suggest to (optionally) add an UNKNOWN value to every enum, and fallback to it on (well) unknown values.

Adding headers to ArtemisClient

First thanks for such a great project. I'm trying to add an call an Amplify graphql server that requires Cognito authorization as follows:

https://github.com/jonsaw/amazon-cognito-identity-dart/#for-appsyncs-graphql

  final body = {
    'operationName': 'CreateItem',
    'query': '''mutation CreateItem {
        createItem(name: "Some Name") {
          name
        }
      }''',
  };
  http.Response response;
  try {
    response = await http.post(
      '$_endpoint/graphql',
      headers: {
        'Authorization': _session.getAccessToken().getJwtToken(),
        'Content-Type': 'application/json',
      },
      body: json.encode(body),
    );
  } catch (e) {
    print(e);
  }
  print(response.body);

Is it possible to pass custom headers to through ArtemisClient so that I can include the appropriate Authorization header?

How to resolve interface?

Hello,

I did not find any example with the artemis package on how to use the type_name_field argument in the build.yaml to resolve interface.
Does anyone have an idea on how to do it?

Thanks in advance.

Lazy Getters

The way graphql_flutter implements NormalizedCache would require denormalizing data on every build call, making allocations for everything under that type for fields that may not be even relevant.

Like a list of friends and respective chat history that would require denormalizing the chat history and allocate it event if I just asked for the friends names.

I would suggest using lazy getters that use their public Map<String,dynamic> interface to interact with data.

That means type generation becomes "cost free" as the compiler would remove most of the indirection it generates and wouldn't require any allocation, dereferencing, etc.

The way I'm currently dealing with it is like this:

  # addressAutosuggest: [AddressAutosuggestResponse!]!
  addressAutosuggest {
    locationName # String!
    latitude # Float!
    longitude # Float!
  }
// generated

class AddressAutosuggestAddressAutosuggestResponse {
  AddressAutosuggestAddressAutosuggestResponse(this._d);

  final Map<String, dynamic> _d;

  String get locationName => this._d["locationName"];
  double get latitude => this._d["latitude"].toDouble();
  double get longitude => this._d["longitude"].toDouble();

}

class AddressAutosuggest {
  AddressAutosuggest(this._d);

  final Map<String, dynamic> _d;

  List<AddressAutosuggestAddressAutosuggestResponse> get addressAutosuggest =>
      (this._d["addressAutosuggest"] as List)
          .map<AddressAutosuggestAddressAutosuggestResponse>(
              (dynamic addressAutosuggestResponse) =>
                  AddressAutosuggestAddressAutosuggestResponse(
                      addressAutosuggestResponse))
          .toList();

}

Seems not working with GitHub search query

Thanks for this lib, really amazing!

I'm planning to replace all the GraphQL queries with artemis in my app, and have some problems with GitHub search API:

{
  search(first: 10, type: REPOSITORY, query: "flutter") {
    nodes {
      __typename
      ... on Repository {
        name
      }
    }
  }
}

Seems the generated dart file has several analyzer errors. The schema file could be found here.

[Question] Is it possible to keep schema file out of /lib folder?

I tried to keep my.schema.json file in the root directory of the flutter app (one directory before /lib). But, the files couldn't be generated.

targets:
  $default:
    sources:
      - lib/**
    builders:
      artemis:
        options:
          schema_mapping:
            - schema: my.schema.json
              queries_glob: lib/**.query.graphql
              resolve_type_field: __typename

Then, I try to use schema: ./my.schema.json, but didn't work as well.
And then, I tried to use schema: lib/my.schema.json and also moved the file to inside /lib folder, so it managed to work well and generate the files.

[Feature Request] Generate types from @gql annotations

In relay, one of the strength points is that queries and fragments can be written along side the widgets using them.

We had a discussion regarding this here.

For example:

@gql(r"""
  query MyHomePage_query {
    ...AllFilmsList_allFilms
  }
""")
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return QueryBuilder(
      query: MyHomePage_query(),
      builder: (context, QueryResponse<$MyHomePage_query> response) { 
        // The QueryBuilder implicitly exposese through context the AllFilmsList_allFilms fragment
        return AllFilmsList();
      }
    );
  }
}

@gql(r"""
  fragment AllFilmsList_allFilms {
    allFilms {
      title
    }
  }
""")
class AllFilmsList extends StatelessWidget {
  const AllFilmsList({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FragmentBuilder<$AllFilmsList_allFilms>(
      builder: (context, allFilms) {

      }
    );
  }
}

I also have been able to make vscode to auto-complete me inside the annotation's query.

What do you think?

Automatically generate dart file for each query.qraphql file

It would be nice if the plugin could automatically generate a dart file for each query.graphql file.

Also it should generate a types.dart which contains all shared types like enums.

This would make it more easy for me to work with the "simple" naming_scheme configuration.

[Artemis 6.0.0] Two classes were generated with the same name `DocumentDataType`! -- which is an enum...

Error:

Two classes were generated with the same name `DocumentDataType`!
You may want to:
- Make queries_glob stricter, to gather less .graphql files on a single output
- Use alias on one of the places a field of type `DocumentDataType` is requested
- Change naming_scheme to `pathedWithFields` to avoid duplication

Queries:

query moduleDataDocuments($moduleId: String!) {
  moduleDataDocuments(moduleId: $moduleId) {
    id
    type
    date
    title
    description
    feedback {
      required
      sent
    }
  }
}

query moduleDataDocumentsData($id: String! $moduleId: String!) {
  moduleDataDocumentsData(id: $id moduleId: $moduleId) {
    type
    data
  }
}

DocumentDataType gql schema:

enum DocumentDataType {
  PDF
  IMAGE
}

build.yaml:

targets:
  $default:
    sources:
      - lib/**
      - graphql/**
    builders:
      artemis:
        options:
          schema_mapping:
            - schema: graphql/schema.graphql
              queries_glob: graphql/**.query.graphql
              output: lib/graphql/graphql_api.dart
              naming_scheme: pathedWithFields

I use Artemis 6.0

Why do I get this error? Shouldn't Enums always be the same? Meaning that you can just use the same enum class on both queries?

Changing naming_scheme to pathedWithFields makes no difference.

[Artemis 6.0.0] Two classes were generated with the same name `EntryTimeEntityMixin`

Error:

Two classes were generated with the same name `EntryTimeEntityMixin`!
You may want to:
- Make queries_glob stricter, to gather less .graphql files on a single output
- Use alias on one of the places a field of type `EntryTimeEntityMixin` is requested
- Change naming_scheme to `pathedWithFields` to avoid duplication

fragments_glob.fragment.qraphql:

fragment EntryTimeEntity on EntryTimeEntity {
  lesson
  length
}

query_1.query.graphql:

query moduleDataExams($moduleId: String!) {
  moduleDataExams(moduleId: $moduleId) {
    id
    date
    sClass
    time {
      ...EntryTimeEntity
    }
    subject
    teacher
    comment
  }
}

query_2.query.graphql:

query moduleDataSubst($moduleId: String!) {
  moduleDataSubst(moduleId: $moduleId) {
    entries {
      time {
        ...EntryTimeEntity
      }
      additionalData {
        insteadOf {
          date
          time {
            ...EntryTimeEntity
          }
        }
        postponed {
          date
          time {
            ...EntryTimeEntity
          }
        }
        customType
      }
    }
  }
}

build.yaml:

targets:
  $default:
    sources:
      - lib/**
      - graphql/**
    builders:
      artemis:
        options:
          fragments_glob: graphql/**.fragment.graphql
          schema_mapping:
            - schema: graphql/schema.graphql
              queries_glob: graphql/**.query.graphql
              output: lib/graphql/graphql_api.dart
              naming_scheme: pathedWithFields

I use Artemis 6.0

I'm using the fragment EntryTimeEntity on 2 different queries. Why is this a problem?

Complete schema.graphql
type BaseSchoolEntity {
  id: String!
  name: String!
  city: String!
  theme: SchoolTheme!
  authRequired: Boolean!
}

type DocumentDataEntity {
  type: DocumentDataType!
  data: String!
}

# Document data type
enum DocumentDataType {
  PDF
  IMAGE
}

type DocumentEntity implements ModuleData {
  _type: String!
  title: String!
  description: String!
  date: String!
  type: DocumentDataType!
  id: String!
  feedback: DocumentFeedbackEntity!
}

type DocumentFeedbackEntity {
  required: Boolean!
  sent: Boolean!
  fields: [String!]!
}

type EntryTimeEntity {
  lesson: String!
  length: Int!
}

type ExamEntryEntity implements ModuleData {
  _type: String!
  id: String!
  date: String!
  sClass: String!
  time: EntryTimeEntity!
  subject: String!
  teacher: String!
  comment: String!
}

interface ModuleData {
  _type: String!
}

type ModuleDataEntity implements ModuleData {
  _type: String!
}

type Mutation {
  sickReport(body: sickReport!): SickReportEntity!
}

type PdfDataEntity {
  pdf: String!
}

type Query {
  school: SchoolEntity
  schools: [BaseSchoolEntity!]
  moduleDataSubst(moduleId: String!): [SubstitutionPlanEntity!]
  moduleDataExams(moduleId: String!): [ExamEntryEntity!]
  moduleDataDocuments(moduleId: String!): [DocumentEntity!]
  moduleDataDocumentsData(id: String!, moduleId: String!): DocumentDataEntity!
  pdfData(moduleId: String!): PdfDataEntity!
}

type SchoolEntity {
  id: String!
  name: String!
  city: String!
  theme: SchoolTheme!
  authRequired: Boolean!
  website: String!
  image: String!
  hidden: Boolean!
  codeOfConduct: [String!]!
  features: [SchoolFeatureEntity!]!
  modules: [SchoolModuleEntity!]!
  substData: [[SubstitutionPlanEntity!]!]!
}

type SchoolFeatureEntity {
  type: SchoolInformationFeatureType!
}

# School information feature type
enum SchoolInformationFeatureType {
  SICK_REPORT
}

# School module category
enum SchoolModuleCategory {
  SUBST
  EXAMS
  CAFETERIA
  NEWS
  DOCUMENTS
  OTHER
}

type SchoolModuleEntity {
  dataType: SchoolModuleType!
  id: String!
  category: SchoolModuleCategory!
  suffix: String!
}

# School module type
enum SchoolModuleType {
  SUBST
  EXAMS
  NEWS
  CAFETERIA
  PDF
  DOCUMENTS
}

# School theme
enum SchoolTheme {
  RED
  PINK
  PURPLE
  DEEP_PURPLE
  INDIGO
  BLUE
  LIGHT_BLUE
  CYAN
  TEAL
  GREEN
  LIGHT_GREEN
  AMBER
  ORANGE
  DEEP_ORANGE
  BROWN
  GREY
  BLUE_GREY
}

input sickReport {
  name: String!
  sClass: String!
  message: String!
  attested: Boolean!
  duration: sickReportDuration!
  specialEvent: String!
}

input sickReportDuration {
  start: String!
  end: String!
}

type SickReportDurationEntity {
  start: String!
  end: String!
}

type SickReportEntity {
  name: String!
  sClass: String!
  message: String!
  attested: Boolean!
  duration: SickReportDurationEntity!
  specialEvent: String!
}

# Subst entry type
enum SubstEntryType {
  EVA
  SUBST
  CANCELLED
  EXAM
  NORMAL
  SHIFTED_TO
  INSTEAD_OF
  SPECIAL
  BREAK_SUPERVISORY
  CUSTOM
}

type SubstitutionEntryAdditionalDataEntity {
  taskBy: [String!]!
  postponed: [SubstitutionEntryAdditionalDataTimeEntity!]!
  insteadOf: [SubstitutionEntryAdditionalDataTimeEntity!]!
  customType: String!
}

type SubstitutionEntryAdditionalDataTimeEntity {
  date: String!
  time: EntryTimeEntity!
}

type SubstitutionEntryEntity {
  date: String!
  sClass: String!
  room: String!
  comment: String!
  subject: String!
  newSubject: String!
  missingTeacher: String!
  teacher: String!
  time: EntryTimeEntity!
  type: SubstEntryType!
  additionalData: SubstitutionEntryAdditionalDataEntity!
}

type SubstitutionPlanEntity implements ModuleData {
  _type: String!
  date: String!
  entries: [SubstitutionEntryEntity!]!
  messages: [String!]!
}



Prefixes are probably not being considered in Enums

Prefixes are probably not being considered in Enums.


First of all, thank you for building this useful tool! I'm looking forward to have this implemented on this tool, my project would benefit a lot from this functionality. In the meantime I planned to use add_query_prefix to generate diferent prefixes and avoid the class name collision but I wasn't able to use it with all my queries whenever more than one query returned a graphql enum of the same type, however this setting worked fine with other queries that didn't return an enum of the same type.

Originally posted by @edwjusti in #27 (comment)

Repeated Objects in different paths of the query are not supported

When we have a Query that contains the same Object in different paths with different fields selected the generations does not work as supposed. This is a problem, especially in heavy recursive schemas. For eg:

Schema.graphql

type MyObject {
  id: ID!
  name: String!
  number: Int!
  connections: [MyObject]
}
query MyQuery {
  myObject {
    id
    connections {
      name
      number
    }
  }
}

Given that the Classes are generated based on the Object name, here we would have two conflicting classes of MyObject, with a different set of fields each.

class MyObject {
  final String id;
  final List<MyObject> connections;
}

and

class MyObject {
  final String name;
  final int number;
}

We may have some options to solve this problem, being one of they the same strategy used by Apollo, that is creating classes taking into account the path in the query like: MyQuery_myObject and MyQuery_myObject_connections. However, this ends up creating very unreadable and long-named classes, so if possible would be great to have an alternative.

Make GraphQLQuery JsonSerializable

I'm creating a GraphQL client that persists mutations when offline and runs them when the client comes back online.

I'd like to request that we make the GraphQLQuery class JsonSerializable so that we can easily persist queries for later use.

Error: Input types generated twice?

I get the following Exception when trying to use an input type from my downloaded schema... what am I missing? Thanks!

Exception: Two classes were generated with the same name `Tools$ToolOrderByInput$OrderByArg`!
You may want to:
- Make queries_glob stricter, to gather less .graphql files on a single output
- Use alias on one of the places a field of type `Tools$ToolOrderByInput$OrderByArg` is requested
- File a bug on artemis (https://is.gd/YLSfC2)

lib/graphql/queries.graphql

# Add [__typename] and [id] to every model you want cached

query tools($orderBy: ToolOrderByInput) {
  tools(orderBy: $orderBy) {
    __typename
    id
    name
    state
    updatedAt
  }
}

lib/graphql/schema.g.graphql (partial):

type Query {
  me: User!
  tool(where: ToolWhereUniqueInput!): Tool
  tools(orderBy: ToolOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Tool!]!
}

type Tool {
  id: String!
  name: String!
  isConnected: Boolean!
  state: String
  telemetryUpdatedAt: DateTime!
  createdAt: DateTime!
  updatedAt: DateTime!
}

input ToolOrderByInput {
  id: OrderByArg
  createdAt: OrderByArg
  updatedAt: OrderByArg
  name: OrderByArg
  isConnected: OrderByArg
  state: OrderByArg
  telemetryUpdatedAt: OrderByArg
}

enum OrderByArg {
  asc
  desc
}

build.yaml

targets:
  $default:
    builders:
      artemis:
        options:
          schema_mapping:
            - schema: lib/graphql/schema.g.graphql
              queries_glob: lib/graphql/**[^.g].graphql
              output: lib/graphql/graphql.g.dart
              # resolve_type_field: __typename

GraphQL interfaces

In my schema, I have something like:

type MyType implements Blah & PublicBlahInterface & BlahSharedProperties { ... }

And the generated code got something like

class MyQuery extends MyTypes
    with EquatableMixin
    implements Blah, PublicBlahInterface, BlahSharedProperties {

However Blah, PublicBlahInterface, BlahSharedProperties never got created by the builder.

Nullable Wrapper

As far as I could tell Artemis isn't doing something to address Dart's lack of non nullable types.

I couldn't see a way to deal with it using custom scalars as nullable types wouldn't be addressed.

The way I work around this right now is by using Dartz Option, meaning having to wrap all nullable types with a runtime check to "cast" them.

Is something like this possible?

Here is a snippet of my current generator result and how the generated code deals with it:

query authToken {
  # authToken: String
  authToken 
}
// generated
import 'package:dartz/dartz.dart';

class AuthToken {
  AuthToken(this._d);
  final Map<String, dynamic> _d;

  Option<String> get authToken =>
      option<String>(this._d["authToken"] != null, this._d["authToken"]);
}

# imports / Document parsing middleware

I'd like to use gql's ast.transform to implement an inline imports handler similar to graphql-import or graphql-import-loader, but would need a parser middleware hook to use it with artemis.

Alternatives:

  • Add import handling to artemis natively
  • Concatenate all globbed files and generate query definitions from the resulting blob instead of iterating over them. This has the pro of not limiting users to 1-to-1 mapping of files-to-operations, but might collide with some other design decision that I am unaware of.

Automatically get current schema from api endpoint

If you use the javascript graphql "Apollo", then you don't have do put any schema.json or schema.graphql in your project at all. Apollo automatically gets the current schema just by the url you specify like this:

schema: https://example.myapi.com/gql/graphql

I think it would be cool to have this in artemis as well.

Allow SDL files (.graphql) as schema files

If you use the graphql Playground, it is very easy do download the graphql schema as a .graphql file in the SDL format. This format is very clean an nice to use compared to the introspection schema which is annoying to query and so on..

So it would be very nice to support this.

#8 already mentioned something like this

BUG: Two classes were generated with the same name ... but its only one query...

My code was working in Artemis 3 but since version 4 I get this error:

Show error message:
Exception: Two classes were generated with the same name `ModuleDataSubst$Query$SubstitutionPlanEntity$SubstitutionEntryEntity$SubstitutionEntryAdditionalDataEntity$SubstitutionEntryAdditionalDataTimeEntity$EntryTimeEntity`!
You may want to:
- Make queries_glob stricter, to gather less .graphql files on a single output
- Use alias on one of the places a field of type `ModuleDataSubst$Query$SubstitutionPlanEntity$SubstitutionEntryEntity$SubstitutionEntryAdditionalDataEntity$SubstitutionEntryAdditionalDataTimeEntity$EntryTimeEntity` is requested
- File a bug on artemis (https://is.gd/YLSfC2)
build.yaml
targets:
  $default:
    sources:
      - lib/**
      - graphql/**
    builders:
      artemis:
        options:
          schema_mapping:
            - schema: graphql/schema.graphql
              queries_glob: graphql/moduleDataSubst.query.graphql
              output: lib/graphql/moduleDataSubst.dart
schema.graphql
interface ModuleData {
  _type: String!
}

type Query {
  moduleDataSubst(moduleId: String!): [SubstitutionPlanEntity!]
}

# Subst entry type
enum SubstEntryType {
  EVA
  SUBST
  CANCELLED
  EXAM
  NORMAL
  SHIFTED_TO
  INSTEAD_OF
  SPECIAL
  BREAK_SUPERVISORY
  CUSTOM
}

type SubstitutionEntryAdditionalDataEntity {
  taskBy: [String!]!
  postponed: [SubstitutionEntryAdditionalDataTimeEntity!]!
  insteadOf: [SubstitutionEntryAdditionalDataTimeEntity!]!
  customType: String!
}

type EntryTimeEntity {
  lesson: String!
  length: Int!
}

type SubstitutionEntryAdditionalDataTimeEntity {
  date: String!
  time: EntryTimeEntity!
}

type SubstitutionEntryEntity {
  date: String!
  sClass: String!
  room: String!
  comment: String!
  subject: String!
  newSubject: String!
  missingTeacher: String!
  teacher: String!
  time: EntryTimeEntity!
  type: SubstEntryType!
  additionalData: SubstitutionEntryAdditionalDataEntity!
}

type SubstitutionPlanEntity implements ModuleData {
  _type: String!
  date: String!
  entries: [SubstitutionEntryEntity!]!
  messages: [String!]!
}

moduleDataSubst.query.graphql
query moduleDataSubst($moduleId: String!) {
  moduleDataSubst(moduleId: $moduleId) {
    date
    messages
    entries {
      type
      date
      time {
        lesson
        length
      }
      sClass
      comment
      missingTeacher
      teacher
      subject
      newSubject
      room
      additionalData {
        taskBy
        insteadOf {
          date
          time {
            lesson
            length
          }
        }
        postponed {
          date
          time {
            lesson
            length
          }
        }
        customType
      }
    }
  }
}

Why isn't it working? There are 3 places where I use the EntryTimeEntity but its always the same entity so the generator should just generate it once and use it everywhere. There shouldn't be any conflicts ...

Can't process query when it implements interface

When the root Query implements Node, artemis fails:

Could not find property "eventByEntityIdAndValidUntil" of class "Node". Moving on...
[SEVERE] artemis:artemis on lib/$lib$:

NoSuchMethodError: The getter 'selections' was called on null.
full trace
[INFO] Generating build script...
[INFO] Generating build script completed, took 261ms

[INFO] BuildDefinition:Initializing inputs
[INFO] BuildDefinition:Reading cached asset graph...
[INFO] BuildDefinition:Reading cached asset graph completed, took 94ms

[INFO] BuildDefinition:Checking for updates since last build...
[INFO] BuildDefinition:Checking for updates since last build completed, took 828ms

[INFO] Build:Running build...
[WARNING] artemis:artemis on lib/$lib$:
Could not find property "eventByEntityIdAndValidUntil" of class "Node". Moving on...
[SEVERE] artemis:artemis on lib/$lib$:

NoSuchMethodError: The getter 'selections' was called on null.
Receiver: null
Tried calling: selections
dart:core                                                               Object.noSuchMethod
package:artemis/generator.dart 435:28                                   _extractClasses.<fn>
dart:collection                                                         SetMixin.forEach
package:artemis/generator.dart 423:23                                   _extractClasses
package:artemis/generator.dart 99:19                                    generateQuery
package:artemis/generator.dart 21:21                                    generateLibrary.<fn>
dart:_internal                                                          ListIterable.toList
package:artemis/generator.dart 22:8                                     generateLibrary
package:artemis/builder.dart 75:29                                      GraphQLQueryBuilder.build
package:build                                                           runBuilder
package:build_runner_core/src/generate/build_impl.dart 478:19           _SingleBuild._runForInput.<fn>.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 300:15  _NoOpBuilderActionTracker.trackStage
package:build_runner_core/src/generate/build_impl.dart 476:23           _SingleBuild._runForInput.<fn>.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 434:22           _SingleBuild._runForInput.<fn>
package:pool/pool.dart 127:28                                           Pool.withResource
package:build_runner_core/src/generate/build_impl.dart 430:17           _SingleBuild._runForInput
package:build_runner_core/src/generate/build_impl.dart 378:38           _SingleBuild._runBuilder.<fn>
dart:async                                                              Future.wait
package:build_runner_core/src/generate/build_impl.dart 377:36           _SingleBuild._runBuilder
package:build_runner_core/src/generate/build_impl.dart 323:20           _SingleBuild._runPhases.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 184:15  _NoOpBuildPerformanceTracker.trackBuildPhase
package:build_runner_core/src/generate/build_impl.dart 319:47           _SingleBuild._runPhases.<fn>
package:timing/src/timing.dart 222:44                                   NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 313:32           _SingleBuild._runPhases
package:build_runner_core/src/logging/logging.dart 25:30                logTimedAsync
package:build_runner_core/src/generate/build_impl.dart 270:26           _SingleBuild._safeBuild.<fn>
dart:async                                                              runZoned
package:build_runner_core/src/generate/build_impl.dart 265:5            _SingleBuild._safeBuild
package:build_runner_core/src/generate/build_impl.dart 212:24           _SingleBuild.run
package:build_runner_core/src/generate/build_impl.dart 97:56            BuildImpl.run
package:build_runner_core/src/generate/build_runner.dart 25:14          BuildRunner.run
package:build_runner                                                    BuildCommand.run
package:args/command_runner.dart 197:27                                 CommandRunner.runCommand
package:args/command_runner.dart 112:25                                 CommandRunner.run.<fn>
dart:async                                                              new Future.sync
package:args/command_runner.dart 112:14                                 CommandRunner.run
package:build_runner                                                    run
.dart_tool/build/entrypoint/build.dart 31:22                            main

[INFO] Build:Running build completed, took 169ms

[INFO] Build:Caching finalized dependency graph...
[INFO] Build:Caching finalized dependency graph completed, took 43ms

[SEVERE] Build:
Failed after 220ms
pub finished with exit code 1

When I delete the interface it works fine

-          "interfaces": [
-            {
-              "kind": "INTERFACE",
-              "name": "Node",
-              "ofType": null
-            }
-          ],

Query:

query GetEvent($eventId: UUID!) {
    event: eventByEntityIdAndValidUntil(entityId: $eventId, validUntil: "infinity") {
        title
    }
}

Config:

schema_mapping:
  - output: 'lib/serializers/artemis.dart'
    schema: 'schema.json'
    queries_glob: 'lib/gql/raw/GetEvent.gql'
    resolve_type_field: __typename
    #add_query_prefix: true

Simplified schema:

type Query implements Node {
  nodeId: ID!
  event(nodeId: ID!): Event
  eventByEntityIdAndValidUntil(entityId: UUID!, validUntil: Datetime!): Event
}

type Event implements Node {
  nodeId: ID!
  entityId: UUID!
  validFrom: Datetime!
  validUntil: Datetime!
  title: String
}

interface Node {
  nodeId: ID!
}

Cannot parse input literal

The following mutation fails with due to an {} input literal with
Error on line 2, column 43 of lib/gql/raw/SignIn.gql: Expected an object field name. Generation succeeds if the literal is converted into an input $variable

mutation SignIn {
    authenticated: currentAppUser(input: {}) {
        user: appUser {
            __typename
            entityId
        }
    }
}
dependencies:
  artemis: ^2.0.4
  equatable: ^0.6.1
  gql: ^0.10.0
full flutter pub run build_runner build --verbose output
[INFO] Generating build script...
[INFO] Generating build script completed, took 318ms

[INFO] BuildDefinition:Initializing inputs
[INFO] BuildDefinition:Reading cached asset graph...
[INFO] BuildDefinition:Reading cached asset graph completed, took 120ms

[INFO] BuildDefinition:Checking for updates since last build...
[INFO] BuildDefinition:Checking for updates since last build completed, took 1.0s

[INFO] Build:Running build...
[SEVERE] artemis:artemis on lib/$lib$:

Error on line 2, column 43 of lib/gql/raw/SignIn.gql: Expected an object field name
  ╷
2 │     authenticated: currentAppUser(input: {}) {
  │                                           ^
  ╵
package:gql/src/language/parser.dart 61:5    _Parser._expectToken
package:gql/src/language/parser.dart 553:19  _Parser._parseName
package:gql/src/language/parser.dart 324:18  _Parser._parseObjectField
package:gql/src/language/parser.dart 321:7   _Parser._parseNonConstObjectField
package:gql/src/language/parser.dart 152:22  _Parser._parseAny
package:gql/src/language/parser.dart 409:17  _Parser._parseObject
package:gql/src/language/parser.dart 341:16  _Parser._parseValue
package:gql/src/language/parser.dart 451:14  _Parser._parseArgument
package:gql/src/language/parser.dart 442:44  _Parser._parseNonConstArgument
package:gql/src/language/parser.dart 117:22  _Parser._parseMany
package:gql/src/language/parser.dart 130:14  _Parser._maybeParseMany
package:gql/src/language/parser.dart 434:57  _Parser._parseArguments
package:gql/src/language/parser.dart 535:23  _Parser._parseField
package:gql/src/language/parser.dart 487:12  _Parser._parseSelection
package:gql/src/language/parser.dart 117:22  _Parser._parseMany
package:gql/src/language/parser.dart 474:21  _Parser._parseSelectionSet
package:gql/src/language/parser.dart 252:21  _Parser._parseOperationDefinition
package:gql/src/language/parser.dart 204:18  _Parser._parseExecutableDefinition
package:gql/src/language/parser.dart 173:18  _Parser._parseDefinition
package:gql/src/language/parser.dart 117:22  _Parser._parseMany
package:gql/src/language/parser.dart 159: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
package:artemis/builder.dart 68:30           GraphQLQueryBuilder.build.<fn>

[INFO] Build:Running build completed, took 162ms

[INFO] Build:Caching finalized dependency graph...
[INFO] Build:Caching finalized dependency graph completed, took 74ms

[SEVERE] Build:
Failed after 246ms
pub finished with exit code 1

#0      throwToolExit (package:flutter_tools/src/base/common.dart:28:3)
#1      pubInteractively (package:flutter_tools/src/dart/pub.dart:244:5)
<asynchronous suspension>
#2      PackagesForwardCommand.runCommand (package:flutter_tools/src/commands/packages.dart:239:11)
<asynchronous suspension>
#3      FlutterCommand.verifyThenRunCommand
(package:flutter_tools/src/runner/flutter_command.dart:557:18)
#4      _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:71:64)
#5      _rootRunUnary (dart:async/zone.dart:1132:38)
#6      _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#7      _FutureListener.handleValue (dart:async/future_impl.dart:137:18)
#8      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45)
#9      Future._propagateToListeners (dart:async/future_impl.dart:707:32)
#10     Future._completeWithValue (dart:async/future_impl.dart:522:5)
#11     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:552:7)
#12     _rootRun (dart:async/zone.dart:1124:13)
#13     _CustomZone.run (dart:async/zone.dart:1021:19)
#14     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
#15     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
#16     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#17     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#18     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:116:13)
#19     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:173:5)

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.