GithubHelp home page GithubHelp logo

gqlgenc's People

Contributors

aisbergg avatar mpldr avatar raphaelfff 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

Watchers

 avatar

gqlgenc's Issues

WS: High CPU usage

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.

Don't send 'null' when optional fields are not set

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.

Possible Solution

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!

Subscriptions not working

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.

[input_as_map] Can't send null for slice inputs

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) { ... }

Fieldname "map"

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

[Bug] gen type already defined

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.

[Bug] OperationName is always capitalized

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.

nil pointer deref when trying to run first time

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?

How to handle custom scalars?

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?

Use Optional Types for GraphQL Optional

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 the order of arguments change for a GraphQL input object, we must migrate our existing code
  • When the variable-name order changes but the type order does not, we won't even notice this through our linter
  • auto-completion is not very good for function arguments

When instead we go back to structs but use the Optional concept from above package, we could have the best of both worlds:

  • no order dependencies
  • don't send optional values as nil

Implement Typename as Enum

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.

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.