infiotinc / gqlgenc Goto Github PK
View Code? Open in Web Editor NEWgqlgenc is a fully featured go gql client, powered by codegen
License: MIT License
gqlgenc is a fully featured go gql client, powered by codegen
License: MIT License
I noticed high cpu usage on subscriptions after 30 seconds when no new data comes in. The reason is to be found here:
client/transport/wshandler.go
func (wh *WebsocketHandler) ReadJSON(v interface{}) error {
ctx, cancel := context.WithTimeout(wh.ctx, wh.timeout)
defer cancel()
return wsjson.Read(ctx, wh.Conn, v)
}
When I use no timeout, cpu usage stays low:
func (wh *WebsocketHandler) ReadJSON(v interface{}) error {
return wsjson.Read(wh.ctx, wh.Conn, v)
}
Not sure if this an issue per se as you can provide your own WebsocketHandler anyways.
Continuing the discussion from Yamashou/gqlgenc#64
Given this schema:
input GetFooInput {
optionalParam1: String
optionalParam2: String
}
type Query {
getFoo(input: GetFooInput!): String!
}
this operation:
query getFoo($p1: String, $p2: String) {
getFoo(input: {optionalParam1: $p1, optionalParam2: $p2})
}
and this example code:
package main
import (
"context"
"lol/dgraphclient"
"github.com/infiotinc/gqlgenc/client"
"github.com/infiotinc/gqlgenc/client/transport"
)
func main() {
wstr := &transport.Ws{
URL: "ws://localhost:8686/subscribe",
}
wstr.Start(context.Background())
defer wstr.Close()
httptr := &transport.Http{
URL: "http://localhost:8686/subscribe",
}
tr := transport.SplitSubscription(wstr, httptr)
cli := &client.Client{
Transport: tr,
}
c := dgraphclient.Client{Client: cli}
p1 := "hi"
c.GetFoo(context.Background(), &p1, nil)
}
Following request is being made to the server:
{
"query": "query getFoo ($p1: String, $p2: String) {\n\tgetFoo(input: {optionalParam1:$p1,optionalParam2:$p2})\n}\n",
"operationName": "GetFoo",
"variables": { "p1": "hi", "p2": null }
}
This is problematic, because setting p2
to null
is different than not sending it in the first place.
Sending null
can (and will) invoke actions on the server side. E.g. deleting some database entry.
Therefore it would be great if we could have the concept of undefined
in this golang client, which is of course difficult as golang does not support an undefined
type.
Maybe something like this could work:
type OptionalString struct {
Value *string
}
type GetFooInput struct {
OptionalParam1 *OptionalString `json:"optionalParam1,omitempty"`
OptionalParam2 *OptionalString `json:"optionalParam2,omitempty"`
}
I.e. when optional input types are present (on any depth) an Optional<Type>
type is used in combination with jsons omitempty
tag instead. This behavior could be made configurable via .gqlgenc.yml
.
Case A:
When the field is nil
, it will not be serialized.
Case B:
When it is set to &OptionalString{}
, the client sends null
.
Case C:
When it is set to &OptionalString{Value: "foo"}
, the client sends "foo"
.
Here is an working example:
package main
import (
"encoding/json"
"fmt"
)
type OptionalString struct {
Value *string
}
func (o *OptionalString) MarshalJSON() ([]byte, error) {
return json.Marshal(o.Value)
}
type GetFooInput struct {
OptionalParam1 *OptionalString `json:"optionalParam1,omitempty"`
OptionalParam2 *OptionalString `json:"optionalParam2,omitempty"`
}
func main() {
s := "foo"
f := GetFooInput{
OptionalParam1: &OptionalString{Value: &s},
}
result, err := json.Marshal(f)
if err != nil {
panic(err)
}
fmt.Println(string(result))
}
Which outputs:
{"optionalParam1":"foo"}
It would be great if you could add this feature!
Hi,
I cannot get subscriptions to work. What am I doing wrong? This should be a very simple, working example.
package main
import (
"context"
"fmt"
"github.com/infiotinc/gqlgenc/client"
"github.com/infiotinc/gqlgenc/client/transport"
)
func main() {
wstr := &transport.Ws{
URL: "ws://localhost:8686/subscribe",
}
wstr.Start(context.Background())
defer wstr.Close()
httptr := &transport.Http{
URL: "http://localhost:8686/subscribe",
}
tr := transport.SplitSubscription(wstr, httptr)
cli := &client.Client{
Transport: tr,
}
sub := cli.Subscription(context.Background(), "", "subscription { subscribeFoo { name }}", nil)
for sub.Next() {
msg := sub.Get()
fmt.Println(msg)
}
if err := sub.Err(); err != nil {
panic(err)
}
}
The server is working correctly and I get results for instance with altair.
Schema:
input FooInput {
ids: [String!]
}
Generates:
func WithIDs(v []string) { ... }
I think that instead this should be generated so a list is also nullable:
func WithIDs(v *[]string) { ... }
In clientgen.go:
- genType := r.GetGenType(def.Name)
+ genType := r.GetGenType(NewFieldPath(def.Kind, def.Name).Name())
when using gqlgen v0.17.14, client generation fails.
Hey,
first of all: Thanks for the great work.
I have a mutation like this:
mutation testmutation {
addFile(input: {
Ids: ["xyxy", "xyxy2"]
Maps: {
Id: "daw"
map: ....
}
}){
testSuccess
}
}
The Field "map" is of type Upload!, but map is also a keyword in go. The generator ends up in the following error:
"mixed named and unnamed parameters" because the generated go func has the form
type ObjectInput map[string]interface{}
func ObjectInput(map transport.Upload,probability float64,) ObjectInput {
return map[string]interface{}{
"map": map,
"probability": probability,
}
}
(this is another mutation, but it should be clear)
The generator should filter for some keywords, i.e. map and change it to something like
type ObjectInput map[string]interface{}
func ObjectInput(map_ transport.Upload,probability float64,) ObjectInput {
return map[string]interface{}{
"map": map_,
"probability": probability,
}
}
Any Ideas how to do it and where? I could also do a PR if I had a starting point
Thanks
Schema:
type A {
a: String!
}
type Foo {
blub: String!
aA: A!
}
type Payload {
foo1: Foo!
foo2: Foo!
}
type Query {
getFoo: Payload
}
Operation:
query getFoo {
getFoo {
foo1 {
blub
aA {
a
}
}
foo2 {
blub
aA {
a
}
}
}
}
There is some issue with deeply nested objects that have the same name.
Trying to migrate from https://github.com/shurcooL/graphql for sake of subscriptions, I'm wondering if it is still supported to create the query from the result struct?
How to set the content-type for the Upload file?
Its default value: application/octet-stream
, but I would like to provide a custom one (e.g. "text/csv").
Operation:
mutation foo {
bar
}
Generates:
res, err := Ξc.Client.Mutation(ctх, "Foo", FooDocument, Ξvars, &data)
Note how the generated operation-name Foo
is capitalized while the schema says that it's not capitalized. This is resulting in an error when doing the actual request.
Trying to debug this but haven't gotten to the bottom of it yet.
❯ gqlgenc
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x28 pc=0x100433d00]
goroutine 1 [running]:
github.com/Yamashou/gqlgenc/clientgen.RenderTemplate(0x14000083380, 0x1400bea4fc0, 0x1400bea50e0, 0x1008beb60, 0x0, 0x0, 0x1008beb60, 0x0, 0x0, 0x1008beb60, ...)
/.../go/pkg/mod/github.com/!yamashou/[email protected]/clientgen/template.go:22 +0x2c0
github.com/Yamashou/gqlgenc/clientgen.(*Plugin).MutateConfig(0x140000e4a80, 0x14000083380, 0x140000e4a80, 0x128f3a1e8)
/.../go/pkg/mod/github.com/!yamashou/[email protected]/clientgen/client.go:80 +0x62c
github.com/Yamashou/gqlgenc/generator.Generate(0x1005f1630, 0x140000ac000, 0x140000d07e0, 0x14000107f50, 0x1, 0x1, 0x14000036800, 0x100081584)
/.../go/pkg/mod/github.com/!yamashou/[email protected]/generator/generater.go:52 +0x230
main.main()
/.../go/pkg/mod/github.com/!yamashou/[email protected]/main.go:30 +0x154
With this yaml config:
model:
package: generated
filename: ./generated/models.go # http://localhost:8080/v1/graphql
client:
package: generated
filename: ./generated/client.go # Where should any generated client go?
models:
Int:
model: github.com/99designs/gqlgen/graphql.Int64
Date:
model: github.com/99designs/gqlgen/graphql.Time
endpoint:
url: http://localhost:8080/v1/graphql # Where do you want to send your request?
headers:
x-hasura-admin-secret: admin-secret # support environment variables
query:
- "./query/*.graphql" # Where are all the query files located?
I have custom scalars like scalar uuid
in my schema.
When generating the client, following panic is thrown:
panic: scalars must be predeclared: uuid
What can we do here? Is this currently completely unsupport as the code suggests?
With go 1.18 generics are now possible to use.
These can be used for example to implement the Optional
concept:
https://github.com/frenchie4111/go-generic-optional
Although the current workaround with input_as_map
works, we also have following issues:
When instead we go back to structs but use the Optional
concept from above package, we could have the best of both worlds:
It would be great if you could implement Typename
as an enum.
Currently a string
type is used which is error prone because you have to type out possible types (e.g. from interfaces or enums) per hand.
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.