heftapp / graphql_codegen Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Does this library supports multiple schema?
I have a case in which the app uses two gql schemas (e.g. test1.schema.graphql
, test2.schema.graphql
) for two different endpoints.
Hi, I've noticed that all classes that have the @JsonSerializable()
metadata (whether they are part of the repository or generated) extend JsonSerializable
. Why is that? As far as I know, this is only adding a few weird properties to every object, like fieldRename
. It's not a requirement of json_serializable
.
Two types with the similar names are converted to the same class name creating duplicate definitions:
Given a graphql schema of:
input SongInput_ {...
and
input SongInput {...
Results in duplicate definitions in the generated *.graphql.dart file
class InputSongInput {
class InputSongInput {
Hi, I have dozens of *.graphql
file that contains schema.
Is it possible to define a "schema directory" in build.yaml
so that it imports all *.graphql
files and use them as schema?
I'm trying to generate the dart data model from the graphql schema and I'm received the following error
➜ octokit.dart git:(main) make gen
dart run build_runner build
[INFO] Generating build script completed, took 788ms
[WARNING] ../../.pub-cache/hosted/pub.dartlang.org/graphql_codegen_config-0.1.2/lib/config.g.dart:31:28: Error: Method not found: '$enumDecode'.
?.map((e) => $enumDecode(_$GraphQLCodegenConfigClientEnumMap, e))
^^^^^^^^^^^
../../.pub-cache/hosted/pub.dartlang.org/graphql_codegen_config-0.1.2/lib/config.g.dart:32:24: Error: The argument type 'Set<dynamic>' can't be assigned to the parameter type 'Set<GraphQLCodegenConfigClient>'.
- 'Set' is from 'dart:core'.
- 'GraphQLCodegenConfigClient' is from 'package:graphql_codegen_config/config.dart' ('../../.pub-cache/hosted/pub.dartlang.org/graphql_codegen_config-0.1.2/lib/config.dart').
.toSet() ??
^
[INFO] Precompiling build script... completed, took 1.3s
[SEVERE] Failed to precompile build script .dart_tool/build/entrypoint/build.dart.
This is likely caused by a misconfigured builder definition.
make: *** [Makefile:16: gen] Error 78
It looks like not related to my source code, but I can be wrong here, the full stack trace is here and in this repository there is the minimal reproducible example.
In addition, this is my build.yaml
targets:
$default:
builders:
graphql_codegen:
options:
clients:
- graphql
When generating for a query like in the docs:
# person.graphql
query FetchPerson($id: ID!) {
fetch_person(id: $id) {
name: full_name
}
}
the example states the generated widget is named Query$FetchPerson
while it is named Query$FetchPersonWidget
instead. This led for me to nearly throw out this package, since it "did not work".
But it DOES works great, once one finds out this.
I restructured and moved the person.graphql
inside lib folder. Now I face an error:
➜ testing flutter clean && flutter pub get && flutter pub run build_runner build
╔════════════════════════════════════════════════════════════════════════════╗
║ A new version of Flutter is available! ║
║ ║
║ To update to the latest version, run "flutter upgrade". ║
╚════════════════════════════════════════════════════════════════════════════╝
Cleaning Xcode workspace... 4.6s
Deleting .dart_tool... 3ms
Deleting .packages... 0ms
Deleting Generated.xcconfig... 0ms
Deleting flutter_export_environment.sh... 0ms
Deleting .flutter-plugins-dependencies... 0ms
Deleting .flutter-plugins... 0ms
Running "flutter pub get" in testing... 3.3s
[INFO] Generating build script...
[INFO] Generating build script completed, took 424ms
[INFO] Precompiling build script......
[INFO] Precompiling build script... completed, took 5.7s
[INFO] Initializing inputs
[INFO] Building new asset graph...
[INFO] Building new asset graph completed, took 581ms
[INFO] Checking for unexpected pre-existing outputs....
[INFO] Checking for unexpected pre-existing outputs. completed, took 1ms
[INFO] Running build...
[SEVERE] graphql_codegen:graphql_codegen on lib/person.graphql:
Invalid GraphQL: Failed to find operation type for OperationType.query
[INFO] Generating SDK summary...
[INFO] 3.1s elapsed, 1/3 actions completed.
[INFO] Generating SDK summary completed, took 3.1s
[INFO] 4.2s elapsed, 1/3 actions completed.
[INFO] 5.3s elapsed, 1/3 actions completed.
[INFO] 7.8s elapsed, 1/3 actions completed.
[INFO] 11.6s elapsed, 1/3 actions completed.
[INFO] Running build completed, took 12.4s
[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 38ms
[SEVERE] Failed after 12.4s
pub finished with exit code 1
This is actually the same error I faced in my original project due to which I decided to make a test project.
Originally posted by @gamer496 in #80 (comment)
Hello,
It seems that there is a problem when generating certain imports with the latest beta version. [0.10.0-beta.3]
The generator created this :
import '../../../../../../repositories/my_schema/schema.graphql.dart';
But the correct one is this :
import '../../../../../../../repositories/kp_commodities/generated/schema.graphql.dart';
My config file :
graphql_codegen:
options:
outputDirectory: '__generated__'
scopes:
- lib/**/my_schema/**
clients:
- graphql
- graphql_flutter
namingSeparator: ''
Don't hesitate to reach me if you need more informations.
Id like to have nested folders
graphql
With the current method, the folders dont marry up.
With an output folder of ../lib/generated_models a folder is generated in the graphql folder instead of its correct placement of the lib/generated_models
This limits the ability to create folders for this tool.
Make folder resolution relative to the package itself, not each graphql file.
I love using this library with the graphql
package for safe type access.
When accessing and writing to the cache though I am largely left to working with untyped maps again. It would be great to generate the readQuery
, writeQuery
, readFragment
and writeFragment
with this package!
I would be happy to help on a PR if @budde377 also thinks this would be a valuable addition?
Hi there!
Im trying to compare artemis with this package however when I tried to run with my own graphQL schema Ive noticed that the generated files have the wrong import for their json_serializeable counterparts.
For example:
The error generated basically says that the part directive should be the file name alone with no reference to the containing folder.
I know its a problem with the outputDirectory
option because it can alter the import directive.
Note: when the outputDirectory isnt set it creates an even worse import:
I dont know your package well but basically the fix would be to remove all folders/to/this/file in the part directive and let json_serializeable do its thing.
bad imports seen above, compiled on windows
Import should be simply the file name
part "lib/./example.graphql.g.dart" -> part "example.graphql.g.dart"
In case if model contains variable with underscore ex. _id
, it's ignored and not used.
I want to know if it's possible to change the naming of the generated class, mainly the $
sign.
Because I want to re-use those classes not only for the graphql api call, for example those enums. But most generators will fail with a property whose name has a $
.
Suppose a schema and fragments as given below
type Tournament {
event: String!
match: Match
}
type Match {
homeTeam: Score
awayTeam: Score
}
type Score {
teamName: String!
value: Int!
}
fragment Tournament on Tournament {
event
match {
homeTeam {
...Score
}
awayTeam {
...Score
}
}
}
fragment Score on Score {
teamName
value
}
The code generated creates a class called FragmentTournament$match whose copywith is as given below
extension UtilityExtensionFragmentTournament$match on FragmentTournament$match {
FragmentTournament$match copyWith(
{FragmentTournament$match$homeTeam? Function()? homeTeam,
FragmentTournament$match$awayTeam? Function()? awayTeam,
String? $__typename}) =>
FragmentTournament$match(
homeTeam: homeTeam == null ? this.homeTeam : homeTeam(),
awayTeam: awayTeam == null ? this.awayTeam : awayTeam(),
$__typename: $__typename == null ? this.$__typename : $__typename);
}
It's expected to take in the values rather than functions that return those values, as is the norm in copyWith methods
Thanks for the great library. I'm trying to migrate our use case from Artemis. May I know how to handle List of objects and Nullable case of the scalar?
For example, in my schema.graphql, I have a scalar of date. And in some cases, we need to use [date]!. Given the following build.yaml config, the generation outputs errors.
date:
type: DateTime
fromJsonFunctionName: fromGraphQLDateNullableToDartDateTimeNullable
toJsonFunctionName: fromDartDateTimeNullableToGraphQLDateNullable
import: package:app/data/model/scalar/graphql_scalar.dart
I know it would be a big chunk of work, but are there any thoughts about integrating freezed when dealing with unions, allowing the interface to be more exhaustive.
Looking at the readme there seems to be only support for fragments but when searching code base I can see references for InlineFragments https://graphql.org/learn/queries/#inline-fragments
Our query has them and I am not sure how to configure them.
Can you please add some examples or documentation?
Undefined class 'GQLOptionsQueryposts'.
Try changing the name to the name of an existing class, or creating a class with the name 'GQLOptionsQueryposts'.
The method 'GQLOptionsQueryposts' isn't defined for the type 'GQLFQueryposts'.
Try correcting the name to the name of an existing method, or defining a method named 'GQLOptionsQueryposts'.
Any Help !! Not Sure What it is : (
The actual code generation generates only a factory method to create an object from the JSON.
I would like to ask if adding an object method to fill an instance from a JSON could be cool to have, it should be enabled code like the following one
Future<T> query<T extends JsonSerializable>({required QueryOptions query}) async {
var response = await _client.query(query);
if (response.hasException) {
throw Exception(response.exception);
}
var result = newObject<T>();
return result.fromJson(response.data!);
}
Given this graphql sdl:
type Mutation {
user: UserMutation!
}
type Query {
users: [User!]!
}
type User {
id: String!
name: String!
}
type UserMutation {
doStuff: Int!
}
schema {
query: Query
mutation: Mutation
}
the generated file is:
const possibleTypesMap = {};
Any ideas what I'm doing wrong? This is a standard output from async-graphql (rust) and works fine in the playground.
Hi and thanks for the package !
I making some unit test for the graphql client and I would like to know how to mock the QueryResult when perform a query method. Let me explain why I'm block on this:
My test:
test(
'should checkEmailVerified',
() async {
// arrange
when(() => graphqlClient.queryGetEmailVerified())
.thenAnswer((_) async => {}); // HERE the return should be a `QueryResult<QueryGetEmailVerified>`
// act
final result = await datasource.checkEmailVerified();
// assert
},
);
The source code:
@override
Future<bool> checkEmailVerified() async {
try {
final result = await graphQLClient.queryGetEmailVerified();
if (result.parsedData != null) {
return Future.value(result.parsedData?.me.emailVerified);
}
}
I can't find any good example to create the class mock to send to the thenAnswer
. Can someone help me on that ?
I want to change the response data for example.
I can't do that for example, because the BaseOptions is private:
final tResult = QueryResult<QueryGetEmailVerified>(
source: QueryResultSource.network,
options: BaseOptions<QueryGetEmailVerified>() // HERE fail because private
);
Hello,
Great package.
Could you update the example + README.md in the repo and on pub.dev to include examples on how to build and use a Mutation and a Subscription as well? (Calling them, and also displaying the data) It only has a simple Query, and GraphQL related packages should definitely include at least an example for each type in my opinion.
Right now this package's documentation seems very light considering how big it is.
Best regards, and thanks for your commitment,
Tiffaa
Hello,
thanks for the great package! I am wondering if it's possible to generate automatically:
type Person {
id: ID!
firstName: String!
}
to this:
fragment FPerson on Person {
__typename
// all fields from Person here:
id
firstName
}
The problem is I have something like:
query getAllPersons {
listPersons: [Person!]!
getPerson(id: ID!): Person!
}
In that case I don't have a unified "Person" class in the generated classes.
Hello,
first of all thanks for the great package! It's priceless!
I have the following schema:
type Query {
listProducts(limit: Int, nextToken: String): ProductsConnection!
}
type Product {
id: ID!
title: String!
content: String!
}
type ProductsConnection {
items: [Product!]
nextToken: String
}
type Mutation {
createProduct(input: CreateProductInput!): Product!
}
input CreateProductInput {
title: String!
content: String!
}
How to build and pass the "CreateProductInput" to the mutation request?
It's fine with the atomic types (int, String etc.). Can't get it working with Input objects.
Thanks!
First of all thanks for this great library. I am migrating my Graphql code from the ferry
package right now and the generated code here is a lot more straightforward and reusable.
I have the following mutation:
mutation CreateEmailInvites($invites: [invites_insert_input!]!) {
insert_invites(objects: $invites) {
returning {
id
}
}
}
and using it with the generated client code for the graphql
package like so:
_client.watchMutationCreateEmailInvites(
GQLWatchOptionsMutationCreateEmailInvites(
eagerlyFetchResults: true,
variables: VariablesMutationCreateEmailInvites(
invites: inviteInputs
.map(
(invite) => InputinvitesInsertInput(
inviteCode: invite.inviteCode,
email: invite.email,
inviterId: invite.inviterId,
name: invite.name,
),
)
.toList(),
),
),
)
Now the issue is that the Invites
model in my graphql API has additional optional values that I am not passing along, but instead of omitting them the generated payload in the final request sets them to null
:
{
"operationName": null,
"variables": {
"invites": [
{
"created_at": null,
"email": "[email protected]",
"id": null,
"invite_code": "VIMtrBLA40",
"invitee_id": null,
"inviter_id": "886f91c3-4162-4391-a187-7cad9c9b666d",
"name": "Johannes",
"profile": null,
"status": null
}
]
},
"query": "mutation CreateEmailInvites($invites: [invites_insert_input!]!) {\n insert_invites(objects: $invites) {\n returning {\n id\n __typename\n }\n __typename\n }\n __typename\n}"
}
My graphql server rejects this request as null
values are not allowed on these fields.
How can one send a partial insert or update request without including other fields as null values? Thanks a lot for your help.
The official dart extension for vscode (and maybe other IDEs?) will only do auto-completion as you type for dart types that are included in the dart analyzer. If they are excluded from the dart analyzer, if you do type the full/correct type name, then it does recognize it still. However, since the auto-generated type names can be quite long, it's more productive to have these auto-completed. And currently if you do not exclude the auto-generated code from the analyzer, it adds lots of warnings to the IDE's list of problems (which I strive to keep at zero).
For the auto-generated files to pass the analyzer without adding warnings, the following could be generated at the top of each auto-generated file:
// ignore_for_file: constant_identifier_names, unnecessary_const
// ignore_for_file: unnecessary_this, annotate_overrides
(The code gen could be adjusted to fix the root cause of all but the first one of these; changing the identifier name pattern would be a breaking change and I personally like the auto-generated constants as they are (all upper separated by underscores)).
What do you think?
(P.S. thanks for adding client codegen for subscriptions, and for the query parseFn! those are working beautifully!!)
I have AllPosts
query ,with Generated GQLFetchMoreQueryAllPosts
function , I Get an UnImplemented Error: Please provide a parser function to support result parsing.
Without codegen i use like below
fetchMore!(
FetchMoreOptions(
variables: {'endCursor': endCursor},
updateQuery: (prev, moreRes) {
final posts = [
...prev!['posts']['nodes']
as List<dynamic>,
...moreRes!['posts']['nodes']
as List<dynamic>
];
moreRes['posts']['nodes'] = posts;
return moreRes;
},
),
),
This would allow the use of TextFormField.onSaved directly on the graphql input
Behaviour:
If I want to update an existing object in a backend, it should only update the provided field and input values and ignore the NULL values. But also the NULL values will be applied too.
Examples:
Mutation:
mutation UpdatePlace($id: ID!, $input: update_places_input!) {
update_places_item(id: $id, data: $input) {
id
status
name
}
}
Variables:
{
"id": "7de55d8d-5ec5-4188-8a38-54e6938f60c1",
"input": {
"city": {
"id": "617a9e1c-3cc5-499f-bbc0-68a904b8a97c"
}
}
}
Execution works with the Altair Client well. But not in Dart:
final updatePlace = await _placeService.updateOnePlace(
placeInput: Input$update_places_input(
id: '7de55d8d-5ec5-4188-8a38-54e6938f60c1',
status: 'published',
name: 'Ein aktualisierter Standort2kk4',
map_location: <String, dynamic>{
'type': 'Point',
//longtiude, latitude
'coordinates': [10.055311, 53.564489]
},
city: Input$update_cities_input(
id: '7de55d8d-5ec5-4188-8a38-54e6938f60c1',
),
),
);
final GraphQLClient _client;
@override
Future<Mutation$UpdatePlace$update_places_item?> updateOnePlace({
required Input$update_places_input placeInput,
}) async {
final options = Options$Mutation$UpdatePlace(
variables: Variables$Mutation$UpdatePlace(
input: placeInput,
id: placeInput.id!,
),
);
final result = await _client.mutate$UpdatePlace(options);
if (result.hasException) {
throw Exception(result.exception.toString());
}
return result.parsedData?.update_places_item;
}
}
Expectation
Ignore the null values in fields and inputs and update only the provided values
When running "flutter pub run build_runner build" I'm receiving the following error:
`[INFO] Generating build script...ild
[INFO] Generating build script completed, took 595ms
[INFO] Initializing inputs
[INFO] Reading cached asset graph...
[INFO] Reading cached asset graph completed, took 80ms
[INFO] Checking for updates since last build...
[INFO] Checking for updates since last build completed, took 375ms
[INFO] Running build...
[SEVERE] graphql_codegen:graphql_codegen on lib/GraphQL/getFriends.graphql:
Null check operator used on a null value
[SEVERE] graphql_codegen:graphql_codegen on lib/GraphQL/schema.graphql:
Null check operator used on a null value
[INFO] Running build completed, took 153ms
[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 39ms
[SEVERE] Failed after 208ms
pub finished with exit code 1
`
For Reference here is my Schema
""" The
@deferdirective may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with
@deferdirective will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response.
@includeand
@Skiptake precedence over
@defer`.
"""
directive @defer(
"""
If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to.
"""
label: String
"""
Deferred when true.
"""
if: Boolean
) on FRAGMENT_SPREAD | INLINE_FRAGMENT
"""
The @stream
directive may be provided for a field of List
type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. @include
and @skip
take precedence over @stream
.
"""
directive @stream(
"""
If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to.
"""
label: String
"""
The initial elements that shall be send down to the consumer.
"""
initialCount: Int!
"""
Streamed when true.
"""
if: Boolean!
) on FIELD
"""
Delegates a resolver to a remote schema.
"""
directive @DeleGate(
"""
The path to the field on the remote schema.
"""
path: String
"""
The name of the schema to which this field shall be delegated to.
"""
schema: Name!
) on FIELD_DEFINITION
directive @computed(
"""
Specifies the fields on which a computed field is dependent on.
"""
dependantOn: [Name!]
) on FIELD_DEFINITION
"""
Annotates the original name of a type.
"""
directive @source(
"""
The original name of the annotated type.
"""
name: Name!
"""
The name of the schema to which this type belongs to.
"""
schema: Name!
) repeatable on ENUM | OBJECT | INTERFACE | UNION | INPUT_OBJECT | FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION | ENUM_VALUE
type Query {
posts: [Post!]!
postById(input: GetPostByIdInput!): GetPostByIdPayload!
communities: [Community!]!
communityById(input: GetCommunityByIdInput!): Community!
users: [User]
userById(input: GetUserByIdInput): GetUserByIdPayload
relationsById(input: GetRelationsByIdInput): [Relationship]
friends(input: GetFriendsInput): [Relationship]
pendingFriendRequests(input: GetPendingFriendRequestsInput): [Relationship]
declinedFriendRequests(input: GetDeclinedFriendRequestsInput): [Relationship]
blockedFriendRequests(input: GetBlockedFriendRequestsInput): [Relationship]
listOfJoinedCommunitiesFromSessions(
input: GetListOfJoinedCommunitiesFromSessionsInput!
): [Uuid!]!
messageById(input: GetMessageByIdInput!): [Message!]!
messageByAuthor(input: GetMessageByAuthorInput!): [Message!]!
messageByRecipient(input: GetMessageByRecipientInput!): [Message!]!
messageByAuthorAndRecipient(
input: GetMessageByAuthorAndRecipientInput!
): [Message!]!
lobbiesByCommunity(input: GetLobbiesByCommunityInput!): [Lobby!]!
}
type Mutation {
addPost(input: AddPostInput!): AddPostPayload!
deletePost(input: DeletePostInput!): DeletePostPayload!
updatePost(input: UpdatePostInput!): UpdatePostPayload!
addCommunity(input: AddCommunityInput!): AddCommunityPayload!
removeCommunity(input: RemoveCommunityInput!): RemoveCommunityPayload!
updateCommunityName(
input: UpdateCommunityNameInput!
): UpdateCommunityNamePayload!
addUserToCommunity(
input: AddUserToCommunityInput!
): AddUserToCommunityPayload!
inviteUserToCommunity(
input: InviteUserToCommunityInput!
): InviteUserToCommunityPayload!
removeUserFromCommunity(
input: RemoveUserFromCommunityInput!
): RemoveUserFromCommunityPayload!
banUserFromCommunity(
input: BanUserFromCommunityInput!
): BanUserFromCommunityPayload!
addUser(input: AddUserInput): AddUserPayload
removeUser(input: RemoveUserInput): RemoveUserPayload
createRelation(input: CreateRelationInput): CreateRelationPayload
acceptRelation(input: AcceptRelationInput): AcceptRelationPayload
declineRelation(input: AcceptRelationInput): AcceptRelationPayload
blockRelation(input: BlockRelationInput): BlockRelationPayload
addNewMessage(input: AddNewMessageInput!): AddNewMessagePayload!
}
type AddPostPayload {
post: Post!
}
type DeletePostPayload {
isDeleted: Boolean!
}
type GetPostByIdPayload {
post: [Post!]!
}
type Post {
id: Int
body: String
createdAt: DateTime
postedFromUserID: Uuid
countUpVoted: Int
countDownVotes: Int
countTotalEngagment: Int
}
type UpdatePostPayload {
post: Post!
}
input AddPostInput {
post: PostInput!
user: UserInput!
}
input DeletePostInput {
post: PostInput!
}
input GetPostByIdInput {
id: Uuid!
}
input PostInput {
id: Int
body: String
createdAt: DateTime
postedFromUserID: Uuid
countUpVoted: Int
countDownVotes: Int
countTotalEngagment: Int
}
input UpdatePostInput {
post: PostInput!
}
input UserInput {
guid: Uuid!
displayName: String
firstName: String
lastName: String
email: String
}
input communities_UserInput {
id: Int!
status: Int
communityId: Int!
guid: Uuid!
displayName: String!
firstName: String!
lastName: String!
email: String!
}
type AddCommunityPayload {
community: Community!
}
type AddUserToCommunityPayload {
user: User!
}
type BanUserFromCommunityPayload {
user: User!
}
type Community {
id: Int!
guid: Uuid!
communityName: String!
dateCreated: DateTime!
userCount: Int!
users: [User!]!
avatar: String!
}
type InviteUserToCommunityPayload {
user: User!
}
type RemoveCommunityPayload {
guid: Uuid!
}
type RemoveUserFromCommunityPayload {
user: User!
}
type UpdateCommunityNamePayload {
guid: Uuid!
}
type User {
id: Int!
status: Int
communityId: Int!
guid: Uuid!
displayName: String!
firstName: String!
lastName: String!
email: String!
}
type users_User {
id: Int!
guid: Uuid!
displayName: String
firstName: String
lastName: String
email: String
}
input AddCommunityInput {
guid: Uuid!
name: String!
userCount: Int
avatar: String
}
input AddUserToCommunityInput {
user: communities_UserInput!
community: Uuid!
}
input BanUserFromCommunityInput {
user: communities_UserInput!
community: Uuid!
}
input GetCommunityByIdInput {
guid: Uuid!
}
input InviteUserToCommunityInput {
user: communities_UserInput!
community: Uuid!
}
input RemoveCommunityInput {
guid: Uuid!
}
input RemoveUserFromCommunityInput {
user: communities_UserInput!
community: Uuid!
}
input UpdateCommunityNameInput {
guid: Uuid!
name: String!
}
type AcceptRelationPayload {
isAccepted: Boolean!
}
type AddUserPayload {
user: users_User
}
type BlockRelationPayload {
isBlocked: Boolean!
}
type CreateRelationPayload {
isCreated: Boolean!
}
type GetUserByIdPayload {
user: users_User
}
type Relationship {
id: Int!
user1Id: Uuid!
user2Id: Uuid!
status: Int!
lastActionUser: Uuid!
}
type RemoveUserPayload {
guid: Uuid!
}
input AcceptRelationInput {
user1Guid: Uuid!
user2Guid: Uuid!
}
input AddUserInput {
guid: Uuid!
displayName: String
email: String
firstName: String
lastName: String
}
input BlockRelationInput {
user1Guid: Uuid!
user2Guid: Uuid!
}
input CreateRelationInput {
user1Guid: Uuid!
user2Guid: Uuid!
status: Int!
lastActionUser: Uuid!
}
input GetBlockedFriendRequestsInput {
guid: Uuid!
}
input GetDeclinedFriendRequestsInput {
guid: Uuid!
}
input GetFriendsInput {
guid: Uuid!
}
input GetPendingFriendRequestsInput {
guid: Uuid!
}
input GetRelationsByIdInput {
guid: Uuid!
}
input GetUserByIdInput {
guid: Uuid!
}
input RemoveUserInput {
guid: Uuid!
}
type AddNewMessagePayload {
message: Message!
}
type Lobby {
id: Int!
lobbyGuid: Uuid!
communityGuid: Uuid!
name: String
dateCreated: DateTime!
maxConnectionsAllowed: Int!
currentConnectionCount: Int!
isPrivate: Boolean!
avatar: String
}
type Message {
id: Int
authorGuid: Uuid!
recipientGuid: Uuid!
msgBody: String!
timeStamp: DateTime!
read: Boolean
sent: Boolean
}
input AddNewMessageInput {
authorGuid: Uuid!
recipientGuid: Uuid!
msgBody: String!
timeStamp: DateTime!
}
input GetListOfJoinedCommunitiesFromSessionsInput {
guid: Uuid!
}
input GetLobbiesByCommunityInput {
communityGuid: Uuid!
}
input GetMessageByAuthorAndRecipientInput {
authorGuid: Uuid!
recipientGuid: Uuid!
}
input GetMessageByAuthorInput {
guid: Uuid!
}
input GetMessageByIdInput {
id: Int!
}
input GetMessageByRecipientInput {
guid: Uuid!
}
"""
The name scalar represents a valid GraphQL name as specified in the spec and can be used to refer to fields or types.
"""
scalar Name
scalar Uuid
"""
The DateTime
scalar represents an ISO-8601 compliant date time type.
"""
scalar DateTime
**Also here is my query used for testing**
query {
friends(input: {guid: "63f8720e-b193-4828-9174-a57bde0e5717"}) {
user1Id
user2Id
lastActionUser
}
}`
Generator fails when I try to generate this graphql (the commented out field)
Bad state: Failed to generate type.
schema {
query: Query
}
type Competition {
"Country code of the competition."
countryCode: String
"Relative URL for the country flag of the competition."
flagUrl: String
"Unique ID of the competition."
id: Int!
"Localized name."
name(locale: Locale = en_US): String
}
type Query {
competitions(
"Filter competitions by date. If not provided, the default value is current date."
date: DateTime,
"If it's true, retrieve competitions with live matches only."
live: Boolean = false
): [Competition!]!
}
type Team {
"Number of goals on the current match."
goals: Int
"Unique ID of the team."
id: Int!
"Relative URL to the jersey image of current team."
jerseyUrl: String
"Lineup and bench players of the team on the current match."
lineup: [Person!]!
"Localized name."
name(locale: Locale = en_US): String
"Localized TLA name."
tlaName(locale: Locale = en_US): String
}
enum Locale {
da_DK
de_DE
el_GR
en_US
es_ES
fr_FR
it_IT
nl_NL
pl_PL
pt_BR
tr_TR
}
"A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format."
scalar DateTime
query MainPage($date: DateTime!, $locale: Locale!, $live: Boolean!) {
competitions(date: $date, live: $live) {
id
flagUrl
name(locale: $locale)
...basicTeamInfo
}
}
fragment basicTeamInfo on Team {
id
goals
#name(locale: $locale)
jerseyUrl
}
Motivation :
schema.graphql
without having to indicate itWhat is less great is that all the generated Dart
files get mixed up with our "original" .graphql
files
Solution :
It would be nicer if the generated Dart files -> were generated in a sub-folder named gen
or generated_graphql
Or being able to choose the output directory
I creating a sample test project.
Dependencies
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
graphql_flutter: ^5.1.0
json_annotation: ^4.5.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
build_runner: ^2.1.11
graphql_codegen: ^0.8.0
json_serializable: ^6.2.0
I also created schema.graphql
and person.graphql
similar to example on pub.dev
Then I try to generate types:
flutter clean && flutter pub get && flutter pub run build_runner build
This runs successfully but does not generate anything. Am I doing something wrong?
Version: graphql_codegen: 0.10.0-beta.5
Generator finds .graphql
files but fails to generate .g
files which are referenced in schema.graphql.dart
with part 'schema.graphql.g.dart';
build.yaml
targets:
$default:
builders:
graphql_codegen:
options:
outputDirectory: '__generated__'
namingSeparator: ''
addTypename: true
scalars:
DateTime:
type: DateTime
JSON:
type: Map<String, dynamic>
Upload:
type: String
clients:
- graphql
zino-hofmann/graphql-flutter#1097 adds two new callbacks to the QueryOptions
, these should be generated the same way as onCompleted
is on MutationOptions
.
The json_serializable
dependency adds a runtime dependency to json_annotations
. We can home-roll our serialisation methods which would remove the dependency and simplify setup. Consider if this is the right approach.
First, I'm impressed and excited by this package! This is the only dart package I've come across that can actually successfully generate code from a GraphQL schema generated by Hasura -- these schemas are a bit more complex (supporting lots of operators, search conditions, methods for paging, etc) and it tripped up other dart gql code generators I've tried. Nicely done!
Also, even though it's not documented to work, it looks like it will actually parse and generate code for subscriptions! (not the client part yet, but that's OK). That was another happy surprise!
Hasura only supports one top-level field for subscriptions (for queries/mutations multiple top-level fields are fully supported without issue). In the Hasura schema, this top-level field would correspond to a table or view in the source database.
If you had some GraphQL like:
fragment Friend on ...
subscription ListenToFriends($user_id: String!) {
user_friends(where: {user_id: {_eq: $user_id}}) {
...Friend
}
}
Then with addTypename: true
in build.yaml this will result in generated code with a SelectionSetNode
that contains two FieldNode
s -- one for user_friends
and then another for __typename
:
FieldNode(
name: NameNode(value: '__typename'),
alias: null,
arguments: [],
directives: [],
selectionSet: null)
The other __typename fields that are automatically added are perfectly OK, if I manually remove this top-level __typename filed node from the generated DocumentNode
, then the subscription is able to execute successfully. If the generated code is unmodified, then when the subscription is run, Hasura responds with this error message instead:
[{extensions: {path: $, code: validation-failed}, message: subscriptions must select one top level field}]
I don't know if this may be a problem common to other GraphQL server/subscription implementations. Arguably Hasura should recognize that __typename is not really trying to subscribe to a second field set, and I'll raise the issue there for consideration there.
I wanted to see if it made sense here to add another build.yaml option, something like omitTopLevelSubscriptionTypename: true
(off by default?), that would tell the code generator to not add __typename just on the top-level of a subscription, so that the auto-generated code out of the box would work with Hasura subscriptions. Or perhaps this field might never be needed at the top-level for a subscription and could always be omitted potentially? What do you think?
sorry, there was a mistake in the api, this is no issue related to this library
It's the first time i'm using this package, somehow it doesn't generate the flutter widgets.
changing clients
in build.yaml
does generate outputs but they look the same.
build.yaml
targets:
$default:
builders:
graphql_codegen:
options:
clients:
- graphql
- graphql_flutter
get_all_pokemons.graphql
query AllPokemons {
pokemon_v2_pokemonspecies(order_by: {id: asc}) {
name
id
}
}
get_all_pokemons.graphql.dart
import 'package:json_annotation/json_annotation.dart';
part 'get_all_pokemons.graphql.g.dart';
@JsonSerializable()
class QueryAllPokemons extends JsonSerializable {
QueryAllPokemons(this.pokemon_v2_pokemonspecies);
@override
factory QueryAllPokemons.fromJson(Map<String, dynamic> json) =>
_$QueryAllPokemonsFromJson(json);
final List<QueryAllPokemons$fpokemon_v2_pokemonspecies>
pokemon_v2_pokemonspecies;
@override
Map<String, dynamic> toJson() => _$QueryAllPokemonsToJson(this);
}
@JsonSerializable()
class QueryAllPokemons$fpokemon_v2_pokemonspecies extends JsonSerializable {
QueryAllPokemons$fpokemon_v2_pokemonspecies(this.name, this.id);
@override
factory QueryAllPokemons$fpokemon_v2_pokemonspecies.fromJson(
Map<String, dynamic> json) =>
_$QueryAllPokemons$fpokemon_v2_pokemonspeciesFromJson(json);
final String name;
final int id;
@override
Map<String, dynamic> toJson() =>
_$QueryAllPokemons$fpokemon_v2_pokemonspeciesToJson(this);
}
get_all_pokemons.graphql.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'get_all_pokemons.graphql.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
QueryAllPokemons _$QueryAllPokemonsFromJson(Map<String, dynamic> json) =>
QueryAllPokemons(
(json['pokemon_v2_pokemonspecies'] as List<dynamic>)
.map((e) => QueryAllPokemons$fpokemon_v2_pokemonspecies.fromJson(
e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$QueryAllPokemonsToJson(QueryAllPokemons instance) =>
<String, dynamic>{
'pokemon_v2_pokemonspecies': instance.pokemon_v2_pokemonspecies,
};
QueryAllPokemons$fpokemon_v2_pokemonspecies
_$QueryAllPokemons$fpokemon_v2_pokemonspeciesFromJson(
Map<String, dynamic> json) =>
QueryAllPokemons$fpokemon_v2_pokemonspecies(
json['name'] as String,
json['id'] as int,
);
Map<String, dynamic> _$QueryAllPokemons$fpokemon_v2_pokemonspeciesToJson(
QueryAllPokemons$fpokemon_v2_pokemonspecies instance) =>
<String, dynamic>{
'name': instance.name,
'id': instance.id,
};
pubspec.yaml
name: pokedex
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: '>=2.18.0-109.0.dev <3.0.0'
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
graphql_flutter: ^5.1.0
json_annotation: ^4.5.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
build_runner: ^2.1.10
json_serializable: ^6.2.0
graphql_codegen: ^0.0.1-alpha.1
flutter:
uses-material-design: true
build_runner build output:
[INFO] Generating build script...
[INFO] Generating build script completed, took 284ms
[INFO] Initializing inputs
[INFO] Reading cached asset graph...
[INFO] Reading cached asset graph completed, took 48ms
[INFO] Checking for updates since last build...
[INFO] Checking for updates since last build completed, took 550ms
[INFO] Running build...
[INFO] Running build completed, took 14ms
[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 29ms
[INFO] Succeeded after 51ms with 0 outputs (0 actions)
I am using codegen with graphql as a client. I struggle with uploading files. graphql supports MultipartFile upload (https://pub.dev/packages/graphql#graphql-upload) but i dont understand how to integrate this with codegen. How can i specify the scalar for the Upload type?
Do I have to wrap it in my own class to link it in the build.yaml or can i reference it directly? If so, how would this be done?
I would like to customize the output folder for the generated files and could not find a configuration option so far. In my case the destination folder would be /lib/generated/graphql/.
Is there this possibility or a workaround for this?
In this example, a Condition is an interface. There are many implementations for it. Like AndCondition
, OrCondition
, TimeCondition
, etc.
On top of that, AndCondition
has left and right fields that are also Condition
s.
Unfortunately, the generator currently generates FragmentAndCondition$left and FragmentAndCondition$right classes as you can see in the picture. However, I'd like it to use FragmentCondition classes instead here.
Is this currently possible?
fragment Condition on Condition{
type
}
fragment AndCondition on AndCondition{
...Condition
left {
...Condition
}
right {
...Condition
}
}
For example,
I have a query function:
// get users
Future<List<User>> getUsers({VariablesQueryUsers? variables}) async {
final _result =
await client.queryUsers(OptionsQueryUsers(variables: variables));
if (_result.hasException) throw _result.exception!;
final _users = QueryUsers.fromJson(_result.data!).users;
return _users
.map(
(_user) => User.fromJson(_user.toJson()),
)
.toList();
}
VariablesQueryUsers
:
class VariablesQueryUsers extends JsonSerializable {
VariablesQueryUsers(
{this.where,
this.orderBy,
this.cursor,
this.take,
this.skip,
this.distinct});
...
and these fields can be optional, thus all set to null.
when sending request with this:
_repository
.getUsers(
variables: VariablesQueryUsers(
orderBy: [
InputUserOrderByWithRelationInput(
createdAt: EnumSortOrder.desc,
)
],
take: 10,
),
)
Here I only set the orderBy
and take
, the request body contains all other fields that contain null, which throw the error as my backend doesn't support that. Maybe I missed something, but I am wondering if I can transform the request body before sending it.
I really sorry if I'm writing another issue here, I'm testing some of my ideas and I'm using this library to generate the graphql query compatible with graphql client.
However, I'm not able to run a complex issue in the Github API, in particular, I'm running the following query but I got some null errors during the iteration over the response object.
These are two tests that make the same jobs, but only one works, more on the stack trace here
test('run a query', () async {
var rawClient = await makeRawClient(token: token!);
var query = QueryOptions(document: gql(commitQuery), variables: {
"owner": "vincenzopalazzo",
"repo": "octokit.dart",
});
var response = await rawClient.query(query);
var edges = response.data!["repository"]!["refs"]!["edges"]!;
expect(edges.length, 1);
edges.forEach((element) {
expect(element["node"], isNotNull);
});
});
test('run a query and decode the result in a Object', () async {
var response = await client!.query(
query: GQLOptionsQueryLastCommits(
variables: VariablesQueryLastCommits(
owner: "vincenzopalazzo", repo: "octokit.dart")));
var query = QueryLastCommits.fromJson(response);
expect(query.repository!.refs!.edges!.length, 1);
query.repository!.refs!.edges!.forEach((element) {
expect(element!.node, isNotNull);
});
});
In this case, the following test assert fails
query.repository!.refs!.edges!.forEach((element) {
expect(element!.node, isNotNull);
});
Hi,
I am running the build command but somehow it keeps complaining about something. The error I get is:
FormatException: Invalid UTF-8 byte (at offset 0)
[SEVERE] graphql_codegen:graphql_codegen on lib/api/graphql/otp.graphql:
The file contents are (saved as txt to make github happy):
otp.txt
I am using graphql_flutter and there we can use dart client.writeFragment(fragmentRequest, data);
but we need the fragment document.
Is it possible to export the document?
I have experienced an edge case issue with this library while using it with the Graphql backend-as-a-service Hasura.
Hasura generates as part of other types the following input type:
input jsonb_cast_exp {
String: String_comparison_exp
}
The key String
is very unfortunate naming. It breaks the code generation as it declares this name as a class member:
@JsonSerializable(explicitToJson: true, includeIfNull: false)
class Input$jsonb_cast_exp {
Input$jsonb_cast_exp({this.String});
@override
factory Input$jsonb_cast_exp.fromJson(Map<String, dynamic> json) =>
_$Input$jsonb_cast_expFromJson(json);
final Input$String_comparison_exp? String;
Map<String, dynamic> toJson() => _$Input$jsonb_cast_expToJson(this);
int get hashCode {
final l$String = String;
return Object.hashAll([l$String]);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (!(other is Input$jsonb_cast_exp) || runtimeType != other.runtimeType)
return false;
final l$String = String;
final lOther$String = other.String;
if (l$String != lOther$String) return false;
return true;
}
}
As String
is not defined as a type, but as a member in the context of this class the compiler complains.
I am not sure if this issue is in the scope of this library, but would there be a way to solve this when one cannot change the type in the backend? In my case I have filed an issue with Hasura, but I am not sure they will make the changes.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.