Skip to content

Conversation

@emmatown
Copy link
Member

@emmatown emmatown commented Mar 7, 2025

This is a potential solution to the "it's weird and is a lot of copy and pasting big files to get @graphql-ts/schema's API bound to a context with all the types available to make it easy to define circular types" problem.

This is an example of what can be written with it:

Note the type g<...> = ... and the g<"object", Person>, this is the new thing here.

import { initG } from "@graphql-ts/schema";
import { GraphQLSchema, graphql } from "graphql";

type Context = {
  loadPerson: (id: string) => Person | undefined;
  loadFriends: (id: string) => Person[];
};
const g = initG<Context>();
type g<
  Key extends initG.Key,
  Arg extends initG.Arg[Key] = initG.ArgDefaults[Key],
  OtherArg extends initG.OtherArg[Key] = initG.OtherArgDefaults<Arg>[Key],
> = initG<Context, Key, Arg, OtherArg>;

type Person = {
  id: string;
  name: string;
};

const Person: g<"object", Person> = g.object<Person>()({
  name: "Person",
  fields: () => ({
    id: g.field({ type: g.nonNull(g.ID) }),
    name: g.field({ type: g.nonNull(g.String) }),
    friends: g.field({
      type: g.list(g.nonNull(Person)),
      resolve(source, _, context) {
        return context.loadFriends(source.id);
      },
    }),
  }),
});

While this is certainly a strange API, it seems like the least bad option to easily bind the API to a context.

The main question is what precisely should the g type support. Currently it is:

// all the g.* functions except g.field and g.enumValues
inputObject
object
union
interface
nonNull
list
scalar
enum
arg
interfaceField

// the different kinds of types
nullableInputType
nullableOutputType
inputType
outputType
type
nullableType

// inferring
inferArg
inferArgs
inferInputType
inferOutputType

There's some awkward things here:

  • Many of these are not bound to the context, they're just included to make it so you only need to import g and not things from @graphql-ts/schema
  • Field is not included. Field likely isn't a big problem since the type itself shouldn't be used very often since it isn't needed for circularity. It's not included since it would require 4 type params (excluding context)

@emmatown emmatown force-pushed the easier-context-binding branch 4 times, most recently from ca4564d to df8f3e5 Compare March 10, 2025 06:08
@emmatown emmatown force-pushed the use-real-graphql-js-types branch from 1d51000 to 663b3d2 Compare March 10, 2025 06:08
@emmatown emmatown force-pushed the easier-context-binding branch from df8f3e5 to e52af70 Compare March 10, 2025 06:15
@emmatown emmatown force-pushed the easier-context-binding branch from e52af70 to c3e2b68 Compare March 10, 2025 23:40
@emmatown emmatown force-pushed the use-real-graphql-js-types branch from 663b3d2 to 5eafeea Compare March 10, 2025 23:40
@emmatown emmatown force-pushed the easier-context-binding branch from c3e2b68 to 8c90521 Compare March 11, 2025 00:50
@emmatown emmatown force-pushed the easier-context-binding branch from 8c90521 to 646198e Compare March 11, 2025 06:00
@emmatown
Copy link
Member Author

This solution seems unpalatable because of the weirdness of passing a string to determine what kind of thing it is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants