strawberry-graphql / strawberry

A GraphQL library for Python that leverages type annotations 🍓
https://strawberry.rocks
MIT License
3.92k stars 516 forks source link

Joining forces on GraphQL code generation #2400

Open jhnnsrs opened 1 year ago

jhnnsrs commented 1 year ago

Feature Request Type

Description

I am the author and maintainer of the "turms" library, which enables similarly to strawberry codegen the generation of graphql types for schema and documents.

I just discovered that strawberry wants to support this feature, and was wondering if it made sense to "join forces" on this topic.

Turms is quite stable at this point and has support for interfaces (as well typecasting to the correct subfragments), is able to generate python functions with typehints, and has extensive configuration options for mixins (traits), additional bases, additional scalars, and is extensible through plugins.

https://github.com/jhnnsrs/turms

I am currently thinking about generating a strawberry schema plugin, but wanted to get some feedback first :)

Upvote & Fund

Fund with Polar

patrick91 commented 1 year ago

Hi @jhnnsrs do you want to chat about this on discord (maybe we can do a call?), I think there are things we can do together!

jhnnsrs commented 1 year ago

A little dicussion later we have this little protoype plugin for turms that can convert this sdl schema

type Beast {
  "ID of beast (taken from binomial initial)"
  id: ID
  "number of legs beast has"
  legs: Int
  "a beast's name in Latin"
  binomial: String
  "a beast's name to you and I"
  commonName: String
  "taxonomy grouping"
  taxClass: String
  "a beast's prey"
  eats: [Beast]
  "a beast's predators"
  isEatenBy: [Beast]
}

type Query {
  """
  get all the beasts on the server
  """
  beasts: [Beast]
  beast(id: ID!): Beast!
  calledBy(commonName: String!): [Beast]!
}

type Mutation {
  """
  create a massive beast on the server
  """
  createBeast(
    id: ID!
    legs: Int!
    binomial: String!
    commonName: String!
    taxClass: String!
    eats: [ID]
  ): Beast!
}

type Subscription {
  watchBeast(id: ID!): Beast
}

into a beautiful strawberry schema

import strawberry
from strawberry import ID
from typing import Optional, List, AsyncGenerator
from enum import Enum

@strawberry.type
class Beast:
    id: Optional[ID] = strawberry.field(
        description="ID of beast (taken from binomial initial)"
    )
    legs: Optional[int] = strawberry.field(description="number of legs beast has")
    binomial: Optional[str] = strawberry.field(description="a beast's name in Latin")
    common_name: Optional[str] = strawberry.field(
        description="a beast's name to you and I"
    )
    tax_class: Optional[str] = strawberry.field(description="taxonomy grouping")
    eats: Optional[List[Optional["Beast"]]] = strawberry.field(
        description="a beast's prey"
    )
    is_eaten_by: Optional[List[Optional["Beast"]]] = strawberry.field(
        description="a beast's predators"
    )

@strawberry.type
class Query:
    @strawberry.field(description="get all the beasts on the server")
    def beasts(self) -> Optional[List[Optional[Beast]]]:
        """get all the beasts on the server"""
        return None

    @strawberry.field()
    def beast(self, id: ID) -> Beast:
        return None

    @strawberry.field()
    def called_by(self, common_name: str) -> List[Optional[Beast]]:
        return None

@strawberry.type
class Mutation:
    @strawberry.mutation(description="create a massive beast on the server")
    def create_beast(
        self,
        id: ID,
        legs: int,
        binomial: str,
        common_name: str,
        tax_class: str,
        eats: Optional[List[Optional[ID]]],
    ) -> Beast:
        """create a massive beast on the server"""
        return None

@strawberry.type
class Subscription:
    @strawberry.subscription()
    async def watch_beast(self, id: ID) -> AsyncGenerator[Optional[Beast], None]:
        return None

Once tests are setup and passing i will push the changes to turms !