gql-dart / gql Goto Github PK
View Code? Open in Web Editor NEWLibraries supporting GraphQL in Dart
License: MIT License
Libraries supporting GraphQL in Dart
License: MIT License
method
) just be context? That way, useGETForQueries
could eventually be a standalone a context update operationFor reference, I think the entire graphql/client.dart
HttpConfig
can be overridden through context, which is roughly:
class HttpQueryOptions {
bool includeQuery;
bool includeExtensions;
}
class HttpConfig {
HttpQueryOptions http;
Map<String, dynamic> options;
Map<String, dynamic> credentials;
Map<String, String> headers;
}
I like the SourceNode
approach to import handling, but won't this result in an infinite loop in the event of a circular import?
gql/gql_build/lib/src/utils/reader.dart
Lines 63 to 70 in e8ec7e3
When the Graphql type has a property with name value it will generate schema.gql.dart file with duplicated property names. This happens mostly when using Hasura and its feature Enum which you have a Type with value and comment properties. Here is an example of such issue:
class role_select_column {
const role_select_column(this.value);
final String value;
static const role_select_column comment = role_select_column('comment');
static const role_select_column value = role_select_column('value');
@override
int get hashCode => value.hashCode;
@override
bool operator ==(Object o) => o is role_select_column && o.value == value;
}
I'm not sure what would be the correct approach to fix this issue, my best guess is to rename String value
property to something else when it detects that there is a property with same name.
I mentioned the issue of serializing Context
in #110, but I figured I'd open a separate issue to discuss this further.
As far as I can tell, some way of serializing data passed into Context
is necessary to enable first-class support for offline-first use cases.
For example, let's say we have a mutation that requires passing the userId
as an argument. We might create a ContextEntry
such as the following:
class UserContextEntry extends ContextEntry {
final String userId;
UserContextEntry(this.userId);
@override
List<Object> get fieldsForEquality => [userId];
}
If the app is offline, a GraphQL client will need to persist this data along with the query in order to properly execute the mutation when the app comes back online.
We could potentially work around this using code generators without adjusting the existing Context
implementation. For example, we could create an aggregate builder that searches source code for implementations of ContextEntry
, then builds a serializer that maps type names to types so that ContextEntry
s can be deserialized later. This would, of course, require each ContextEntry
to be serializable, meaning that our UserContextEntry
above would probably need to be extended to something like this:
class UserContextEntry extends ContextEntry implements SerializableContextEntry {
final String userId;
UserContextEntry(this.userId);
@override
List<Object> get fieldsForEquality => [userId];
Map<String, dynamic> toJson() => {"userId": userId};
UserContextEntry fromJson(Map<String, dynamic> json) =>
UserContextEntry(json["userId"]);
}
This is starting to be a lot of boilerplate just to pass a userId
to a mutation.
@klavs @micimize I'd appreciate any insight you may have on this.
Currently, the Request.variables
and Response.data
objects must be json (i.e. Map<String, dynamic>
).
Therefore, in order to implement typed requests and responses (such as those used in ferry
), we must re-implement the Request and Response classes.
I suggest we consider the following changes:
Request
, Response
Request
and Response
abstractRequest
and Response
that uses json for data and vars.For example, Request
might look like this:
abstract class Request<TVars> {
final Operation operation;
final TVars variables;
const Request({
this.operation,
this.variables,
});
}
We could then implement a DefaultRequest
that uses json:
class DefaultRequest extends Request<Map<String, dynamic>> {
@override
final Operation operation;
@override
final Map<String, dynamic> variables;
final Context context;
const DefaultRequest({
@required this.operation,
this.variables = const <String, dynamic>{},
this.context = const Context(),
}) : assert(operation != null),
assert(context != null);
DefaultRequest withContextEntry<T extends ContextEntry>(T entry) =>
DefaultRequest(
operation: operation,
variables: variables,
context: context.withEntry<T>(entry),
);
DefaultRequest updateContextEntry<T extends ContextEntry>(
ContextUpdater<T> update,
) =>
DefaultRequest(
operation: operation,
variables: variables,
context: context.updateEntry<T>(update),
);
List<Object> _getChildren() => [
operation,
variables,
context,
];
@override
bool operator ==(Object o) =>
identical(this, o) ||
(o is DefaultRequest &&
const ListEquality<Object>(
DeepCollectionEquality(),
).equals(
o._getChildren(),
_getChildren(),
));
@override
int get hashCode => const ListEquality<Object>(
DeepCollectionEquality(),
).hash(
_getChildren(),
);
}
Of course, we'd also need to make changes to gql_link
and any other libraries that depend on gql_exec
.
If I link.request
a subscription
(say, with a WebsocketLink
), how do I request it be cancelled later?
The description for ServerException
is:
/// Exception occurring when network fails
/// or parsed response is missing both `data` and `errors`
However, since such an exception could occur on the client and never even reach the server (e.g. if the client is offline), I suggest we rename it to NetworkException
.
I recognize this would be a breaking change for a purely semantic reason, but maybe we can include it in the next major version bump.
Can the schema_builder
generate code for all types defined in the schema to be used as QueryRequest
instead of making a ${{queryName}}
type. Right now a every query has its own return type event if they return the same type.
@klavs have you thought about how to implement interface and union types?
Related to comigor/artemis#49 -
I'd like to add ast_builder
support to graphql-to-dart
, and having it handle imports internally would simplify it considerably. Examples of this pattern in the js world: graphql-import
, graphql-import-loader
I just wanted to start a discussion about the possibility of building data as built_values rather than storing the Json object and using getters.
I find the immutability and serializability of built_value to be compelling, although it would add some complexity.
Thoughts?
I am interested in building graphql server (not using angel framework and its packages).
In this project, what packages can be used to build graphql server?
If you give me a rough idea, it will really be appreciated.
@smkhalsa Issue created from our DIscord discussion
A custom serializer's return type that is imported from another file is not shown in serializers.gql.dart
causing a build error.
Only happens with generated BuiltLists? I have other custom scalars set-up the same way but addBuilderFactory
functions are not generated for them so this problem doesn't occur...
Also, the addBuilderFactory
function is generated multiple times...
Note: build_runner build
is still successful
lib/graphql/schema/serializers.gql.g.dart:182:59: Error: Getter not found: 'MyModel'.
const FullType(BuiltList, const [const FullType(MyModel)]),
^^^^^^^^^^^^^^
lib/graphql/schema/serializers.gql.g.dart:183:33: Error: 'MyModel' isn't a type.
() => new ListBuilder<MyModel>())
^^^^^^^^^^^^^^
# schema.g.graphql
#...
"""JSON encoded custom scalar type"""
scalar MyModelPlural
type Foo {
id: String!
items: [MyModelPlural!]
}
#...
# build.yaml
#...
ferry_generator|req_builder:
enabled: true
options:
schema: flutter_app|lib/graphql/schema/schema.g.graphql
type_overrides:
MyModelsPlural:
name: MyModel
import: 'package:flutter_app/models/my_model.dart'
gql_build|serializer_builder:
enabled: true
options:
schema: flutter_app|lib/graphql/schema/schema.g.graphql
custom_serializers:
- import: 'package:flutter_app/graphql/serializers/my_model_serializer.dart'
name: MyModelSerializer
#...
// my_model_serializer.dart
// ignore: implementation_imports
import 'package:gql_code_builder/src/serializers/json_serializer.dart';
// This import exposes "MyModel" which will be required, but missing, from serializers.gql.dart
import 'package:flutter_app/models/my_model.dart';
class MyModelSerializer extends JsonSerializer<MyModel> {
@override
MyModel fromJson(Map<String, dynamic> data) {
return MyModel.fromJson(data);
}
@override
Map<String, dynamic> toJson(MyModel model) {
return model.toJson();
}
}
// serializers.gql.dart
//...
// Correctly exposes "MyModelSerializer" but NOT "MyModel", causing built file to have missing type
import 'package:flutter_app/graphql/serializers/my_model_serializer.dart'
show MyModelSerializer;
part 'serializers.gql.g.dart';
final SerializersBuilder _serializersBuilder = _$serializers.toBuilder()
..add(OtherSerializer())
..add(MyModelSerializer())
//...
// serializers.gql.g.dart
//...
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(MyModel)]),
() => new ListBuilder<MyModel>()))
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(MyModel)]),
() => new ListBuilder<MyModel>()))
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(MyModel)]),
() => new ListBuilder<MyModel>()))
//...
I've been experimenting with the builders, and I think we should build most of the files to the cache rather than to source. We have 10 builders now, and the number of generated files is overwhelming.
Do any builders other than req_builder
and data_builder
really need to be built to source?
Implement KnownArgumentNamesOnDirectives validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
As discussed here, in order to support building fragment data next to the fragment definitions in source, we need to rethink the import implementation.
In addition, I'd like to suggest that we follow the graphql-import style for imports...
Import specific types:
# import A from 'schema.graphql'
Import multiple types:# import A, B, C from 'schema.graphql'
Import all types:# import * from 'schema.graphql'
Import root fields:# import Query.* from 'schema.graphql'
Import root fields and all types:# import Query.*, Mutation.*, * from 'schema.graphql'
Relative paths:# import Post from "../database/schema.graphql"
I'm running into an issue caused by this change:
2ec3400#diff-de53cc87c4e8bb475234fd501187c9e0R76
The generated .var.gql.dart
file now imports from 'package:[path/to/source/file].schema.gql.dart' (which doesn't exist) rather than from the global .schema.gql.dart
file.
moving this from gql-dart/ferry#7
It would make some use cases easier to implement if there was a type-aware visitor provided. Maybe something that visits AST nodes that have a type
attribute?
I'm basically trying to implement something like what I talk about in comigor/artemis#39, where a base schema_types.dart
file gets generated with just the subset of schema types referenced by the collected operations and fragments.
I've found that a "blank comment" (lines with only #
followed by line terminator) before any important line break gql parser.
For instance, any of the following breaks:
#
schema {
#
query: Query
}
type Query {
object: Object!
#
}
# The next line will be only `#`
#
type Object {
id: String
}
As per spec "Comments" section, it seems they are valid.
Here's a file reproducing this error: schema.graphql
Right now they're all just instance of LinkException
.
Should at least be something like 'LinkException(originalException: $originalException)'
Implement UniqueDirectivesPerLocation validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
Implement KnownDirectives validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
Hey @klavs! I'm getting an error while using the language SDL parser (parseString
) on some of my examples. It say it can't find the Entity interface while parsing the Area object even though it's declared on the same schema:
Error on line 32, column 28 of lib/graphbrainz.schema.graphql: Unknown definition type 'Entity'
╷
32 │ type Area implements Node, Entity {
│ ^^^^^^
╵
package:gql/src/language/parser.dart 175:5 _Parser._parseDefinition
package:gql/src/language/parser.dart 117:22 _Parser._parseMany
package:gql/src/language/parser.dart 142:22 _Parser._parseDocument
package:gql/src/language/parser.dart 41:27 _Parser.parse
package:gql/src/language/parser.dart 17:17 parse
package:gql/src/language/parser.dart 27:5 parseString
The full schema, for referece: graphbrainz.schema.graphql.
This is partially implemented, but still lacks majority of the rules.
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
In graphql-flutter
I closed an issue about a specific solution for accessing response headers a while ago, but never followed up with the correct solution (adding headers to context)
multipack
is not documented and is hard to use. GPM would be a better option. It currently lacks local package linking, but I've already submitted a PR https://github.com/dint-dev/gpm/pull/1
I'm running into an issue with the new import functionality. If I have a query that uses multiple fragments which themselves use a common fragment, the ast_builder
will include multiple instances of the import for that common fragment in its List of definitions.
@klavs I assume we can simply check for uniqueness here, but let me know your thoughts.
Implement ProvidedRequiredArgumentsOnDirectives validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
Is there anyway to cancel a subscription?
I thought it might be a nice implementation to send the server a GQL_STOP payload when the stream is stopped being listened to.
What do you think?
Hi!
Try get new updates for gql_link: ^0.3.0 and gql_http_link: ^0.2.9, and get in
Because gql_http_link >=0.2.9 depends on gql_link ^0.3.0 and lifext depends on gql_link ^0.2.3, gql_http_link >=0.2.9 is forbidden.
So, because lifext depends on gql_http_link ^0.2.9, version solving failed.
pub get failed (1; So, because lifext depends on gql_http_link ^0.2.9, version solving failed.)
If update only gql_link: ^0.3.0
Because ferry 0.3.0 depends on gql_link ^0.2.2 and no versions of ferry match >0.3.0 <0.4.0, ferry ^0.3.0 requires gql_link ^0.2.2.
If update only gql_http_link: ^0.2.9
Because gql_http_link >=0.2.9 depends on gql_link ^0.3.0 and lifext depends on gql_link ^0.2.3, gql_http_link >=0.2.9 is forbidden.
As far as I can tell, there is no way to have multiple queries use shared fragments
i.e.
fragment someFragment on C {
fields
}
query A {
someField
...someFragment
}
query B {
someField
...someFragment
}
A normal use of fragments is to extract shared pieces of queries.
This is pretty important in dart as types are not structural like other languages such as Typescript.
That means if I want to render a shared widget using the query data, I cannot mix and match data from query A and query B even if the types are structurally the same.
I am using grpc in golang and flutter, but I need to add a GraphQL layer too.
https://github.com/graph-gophers Is a pretty nice golang System and I was wondering if someone could recommend a golang server that they use ?
Pedantic enforces single quotes and we shall obey.
I cannot be bothered to do it manually. If anyone has the tool, feel free to run it and also update package:gql_pedantic
rules.
I am working on adding exceptions to WebSocketLink
, the plan is
WebSocketLinkParserException
Exception occurring when parsing fails or parsed response is missing both data
and errors
.
WebSocketLinkServerException
Exception occurring when network fails.
Right now the error "parsed response is missing both data
and errors
." is handled as ServerException
I want to refactor this as ResponseFormatException
.
Any suggestions, should I continue as planned?
As you can see here, we are currently only building data classes for Query
s, not Mutation
s.
Implement UniqueTypeNames validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
Implement UniqueArgumentNames validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
@klavs, I'm working on a GraphQL client that persists mutations when offline and runs them when the client comes back online.
Can we make the DocumentNode class JsonSerializable?
Would be good to expose an extension: '.gql'
option
gql/gql_code_gen/lib/ast_builder.dart
Line 40 in 38805d3
Hello, Klavs! I saw this pop up on my Github feed. If you didn't know, I have existing GraphQL parser/schema/introspection/server libraries here: https://github.com/angel-dart/graphql
It may be easier in the long run to join that project and contribute there.
Of course, though, it is your choice, and completely up to you.
Was wondering why gql_websocket_link
removed the inactivityTimeout
option?
if (config.inactivityTimeout != null) {
_keepAliveSubscription = _messagesOfType<ConnectionKeepAlive>().timeout(
config.inactivityTimeout,
onTimeout: (EventSink<ConnectionKeepAlive> event) {
print(
"Haven't received keep alive message for ${config.inactivityTimeout.inSeconds} seconds. Disconnecting..");
event.close();
_socket.close(WebSocketStatus.goingAway);
_connectionStateController.value =
SocketConnectionState.NOT_CONNECTED;
},
).listen(null);
}
I'm building my own link that utilizes dio
for making HTTP requests instead of http
library. dio have multiple types of errors should I remap them to a exceptions that extend LinkException?
for example, should I do the following or rethrow expectations other than the ones in the gql_link
library?
} on dio.DioError catch (e) {
if (e.type != dio.DioErrorType.RESPONSE) {
final res = e.response;
if (res.data is Map<String, dynamic>) {
final parsedResponse =
parser.parseResponse(res.data as Map<String, dynamic>);
throw DioLinkServerException(
response: res, parsedResponse: parsedResponse);
}
}else if (e.type == dio.DioErrorType.CONNECT_TIMEOUT){
throw DioLinkTimeoutException(originalException:e);
}
else if(...){
...
throw DioLinkXXXException(originalException:e);
}
}catch (e){
throw DioLinkUnkownException(originalException:e);
}
And as I can see the ferry
client only catches LinkException.
https://github.com/gql-dart/ferry/blob/master/lib/src/client/client.dart#L171
Hi,
I was trying out gql_build and ran into an issue:
I defined a schema.graphql file and added a queries.graphql file, where I added multiple queries (say, Query1, Query2, Query3) with different required variables.
This does not seem to work.
In the queries.ast.gql.dart file, there is a line
const document = _i1.DocumentNode(definitions: [Query1, Query2, Query3 ...]);
If I then execute
graphqlClient
.responseStream(Query1(
buildVars: (vars) => vars..query1Var = "test"
)
All Queries (Query1, Query2, Query3) will be executed, but of course, this query fails as the variables for the latter 2 queries are not set.
If I split all the queries in separate files, they work fine.
Is having multiple queries in one .graphql file supported?
If yes, this should be fixed.
If not, this should probably be an error during the build_runner step.
Implement UniqueInputFieldNames validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
Implement KnownTypeNames validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
Let's say I have custom scalars in my schema, e.g. Email
which actually is String
. It's okay that builder generates wrapper class for it. But there are cases when i need that mapping, e.g. with Uint
or Time
. Builder produces a wrapper class which stores value in String
variable, but it's not okay because when I send such variable within query to server, exception occurs. So, the good option to have would be ability to define scalar map in build.yaml
like in artemis
Implement PossibleTypeExtensions validation rule (ref)
Unlike graphql-js
, there is no validation context given when validating a document. A schema validation rule should be self-sufficient and based only on the given AST document.
See https://github.com/gql-dart/gql/tree/master/gql/lib/src/validation.
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.