0no-co / gql.tada

🪄 Magical GraphQL query engine for TypeScript
https://gql-tada.0no.co
MIT License
2.64k stars 44 forks source link

RFC: Create a schema builder that can derive a schema type for gql.tada #10

Open kitten opened 10 months ago

kitten commented 10 months ago

This is part of a future milestone, and currently proposed to close the client-server gap in GraphQL for small projects.

Summary

Currently, GraphQL caters for complex schemas and APIs that are separate from the application they’re built for. However, GraphQL presents a major setup hurdle and makes it hard for people to get started when writing a simple API in a monorepo for a single application, or embedded as an API route into an app.

While this use-case doesn't show all the best strengths of GraphQL at scale and in teams, many individual developers and teams commonly start with one app and one GraphQL schema.

My hypothesis is that it's still too hard to get started with GraphQL compared to tRPC, which tightly couples server and client-types, and allows for a tight integration between its server-side and client-side code.

While gql.tada + @0no-co/graphqlsp currently tightens the feedback loop when writing GraphQL code, this can be improved further.

As part of this proposal, gql.tada should provide a way to create a small GraphQL schema, which can derive its own schema type in TypeScript.

This schema can then be used directly when authoring GraphQL queries with gql.tada, with instant feedback and without reading a schema output from a GraphQL API.

Note: We’re not proposing this to be a replacement for a fully-fledged schema builder, but instead, a schema builder that caters for “embedded” GraphQL API, i.e. single-app GraphQL schemas served on an API route.

Proposed Solution

gql.tada/schema should expose a schema builder, with an API similar to the existing gqtx: https://github.com/sikanhe/gqtx

It should provide a helper to derive a dataloader (or other shared-request objects) from the context object on the fly.

It should provide a utility type that either:

These types should then be converted into gql.tada’s IntrospectionLikeType automatically with this utility type and allow a front-end in the same app or monorepo to pass this type to gql.tada.

Requirements

In short, the resulting gql.tada/schema + gql.tada combo should allow a developer to:

The gql.tada/schema utilities should also output a schema.graphql file in development automatically which @0no-co/graphqlsp can be configured to use.

captbaritone commented 10 months ago

Your goals here feel like they overlap significantly with my goals for Grats. Also, the developer experience goals of gql.tada also feel broadly aligned with those of Grats.

If you're interested, I'd be happy to setup some time to chat. I could share what I've learned while working on Grats, some takeaways from our work on Relay's LSP, and also learn a bit more about your goals.

kitten commented 10 months ago

@captbaritone: Sounds awesome! I’d love to chat about this, so if you’re up for it, I hope we can coordinate something on Twitter, Discord, or via mails ✌️

For context, we’re 100% on the lookout for schema builder maintainers that are willing to implement the above RFC with us into their schema builders (if there’s no additional concerns of course), and even if we build gql.tada/schema it would only be a very basic schema builder that wouldn't cater for anything but really simple use-cases

captbaritone commented 10 months ago

@kitten Sounds good. I've reached out on Twitter.

mxstbr commented 10 months ago

@hayes @JoviDeCroock could Pothos do this as one of the more fully featured options?! 😍

hayes commented 10 months ago

I'm looking to see if there is a way to drive this with a subset of the Pothos API. Pothos currently intentionally avoids knowing the shape of the schema for checking performance reasons. It also makes it easier to avoid issues related to circular references.

I think TS has come a long way since I made some of those decisions, and I'm exploring what might be possible in v4

marcus-sa commented 9 months ago

Your goals here feel like they overlap significantly with my goals for Grats. Also, the developer experience goals of gql.tada also feel broadly aligned with those of Grats.

If you're interested, I'd be happy to setup some time to chat. I could share what I've learned while working on Grats, some takeaways from our work on Relay's LSP, and also learn a bit more about your goals.

Check out https://github.com/marcus-sa/deepkit-graphql

Hebilicious commented 2 days ago

This is a very interesting problem space, and it reminds me of what just happened with xstate :

Xstate is amazing, but state machines can be overkill for simple state management.

So xstate came-up with @xstate/store, which uses a very similar API, but is only 1.2kB and is framework agnostic, and has a very straightforward migration path to the full blown state machine.

In an ideal world, I would want to a similar relationship between gql.tada/server and pothos.

Maybe something like this :

import SchemaBuilder from 'gql.tada/schema';
import server from 'gql.tada/server'

const builder = new SchemaBuilder({});

builder.queryType({
  fields: (t) => ({
    hello: t.string({
      args: {
        name: t.arg.string(),
      },
      resolve: (_, { name }) => `hello, ${name || 'World'}`,
    }),
  }),
});

const schema = builder.toSchema();
server({ schema }).listen()

It would get people started immediately, and then they can easily migrate to a full blown Pothos + Yoga due to the API compatibility.