Authentication-Results: mail-b.sr.ht; dkim=pass header.d=protonmail.com header.i=@protonmail.com Received: from mail-4316.protonmail.ch (mail-4316.protonmail.ch [185.70.43.16]) by mail-b.sr.ht (Postfix) with ESMTPS id 9B49C11EF31 for <~emersion/hut-dev@lists.sr.ht>; Sun, 23 Jan 2022 18:29:32 +0000 (UTC) Date: Sun, 23 Jan 2022 18:29:24 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail2; t=1642962570; bh=DmcYj4h8s8sYLV0wj+3LPwIsa5hCVlmmEiz1g39ReAg=; h=Date:To:From:Cc:Reply-To:Subject:Message-ID:In-Reply-To: References:From:To:Cc; b=HkiWILXAIusDbMyoKCtaJ2FT56iYPq77kBbaWmKN66viRTlT91VPo8ThGXeW5UhqK bcvRGTegzAZzwhXtwi763HB3XcCKu5Hrl5xEEeQzGXrf022wCiWmcDJiycPx1SL8fl k1TZvpkw5TDGeyGfgreoNmWN30J/D3ZpORN0QFf1LNG1sAPZvLA8AihdT1aaz3mFQz 11qjjD+sEFTvpYAetkBzEjCCTAI8XgMEjF6Pk4044LeTASMG71qU9AhkAjHcjVTuQN a+dUaifXZVycJhsu3AZBBUZp72vqUHfqYCFm99Tbs30LRCZ/dldBSO7zC9rsSHt1Nw 6mcHHwKEwGlJA== To: Simon Ser From: Renato Torres Cc: ~emersion/hut-dev@lists.sr.ht Reply-To: Renato Torres Subject: Re: [PATCH v1 0/1] git: show license spike Message-ID: In-Reply-To: References: <20220122233022.1256016-1-renato.torres@protonmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-1.2 required=10.0 tests=ALL_TRUSTED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM shortcircuit=no autolearn=disabled version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on mailout.protonmail.ch I was exploring your comments a bit further (and learned a lot about GraphQL...). If I understood correctly we cannot use "raw" as a generic solution because that's a specific field from the git.sr.ht GraphQL API. I've hacked gqlclient to explore a solution for this. Consider the following schema ("stolen" from 99designs/gqlgen): ```graphql interface Character { # ... } type Human implements Character { # ... } type Droid implements Character { # ... } ``` Instead of generating: ```go type Character struct { // ... } type Human struct { // ... } type Droid struct { // ... } ``` We would generate: ```go type Character interface{} type CharacterFields struct { // ... } type Human struct { // ... } type Droid struct { // ... } ``` And the following methods: ```go func (i *Character) AsCharacterFields() *CharacterFields { bytes, _ :=3D json.Marshal(i) charFields =3D new(CharacterFields) json.Unmarshal(bytes, &charFields) return charFields } func (i *Character) AsHuman() *Human { bytes, _ :=3D json.Marshal(i) obj =3D new(Human) json.Unmarshal(bytes, &obj) return obj } // Etc.... ``` The operations remain unchanged: ```go func Characters(client *gqlclient.Client,=20 ctx context.Context) (characters []Character, err error) { op :=3D gqlclient.NewOperation("query characters ... ") var respData struct { Characters []Character } err =3D client.Execute(ctx, op, &respData) return respData.Characters, err } ``` I don't like very much the "Fields" suffix, eventually we would need to find a better naming schema. Additionally this has the drawback of having to use "AsCharacterFields" to access the fields declared in the GraphQL interface, something that we don't need with the current approach. > It would seem like this is a promise we can make for simple > cases, but not sure about federated GraphQL schemas and schemas split > into multiple files. Would need to do more research. I think with this approach we wouldn't have problems with other cases, because it does not require us to know about all implementations of a GraphQL interface at generation time (but I haven't done a proper=20 research on this...). Example in cmd/gqlclientgen/main.go: ```go // ... func genDef(schema *ast.Schema, def *ast.Definition) *jen.Statement { switch def.Kind { // ... case ast.Object: var stmts []jen.Code var fields []jen.Code for _, field :=3D range def.Fields { //... } for _, i :=3D range def.Interfaces { interfaceName :=3D i stmts =3D append(stmts, jen.Line()) stmts =3D append(stmts, jen.Func().Params(jen.Id("i").Op("*").Id(interfaceName)). Id("As"+def.Name).Params().Params(jen.Op("*"). Id(def.Name)).Block( jen.Id("bytes, _").Op(":=3D"). Qual("encoding/json", "Marshal").Call(jen.Id("i")), jen.Id("obj").Op("=3D").New(jen.Id(def.Name)), jen.Qual("encoding/json", "Unmarshal").Call(jen.Id("bytes"), jen.Id("&obj")), jen.Return(jen.Id("obj")))) } // ... } ``` What do you think? I can send a gqlclient patch if you want to take a look at the code I used to generate this.