Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new graphql.typeName for the structure field to support deduplication of GraphQL types #8480

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

borisno2
Copy link
Member

@borisno2 borisno2 commented Apr 12, 2023

Adds graphql.typeName to structured JSON field to allow structured JSON to have global types
Note if the types don't match it will cause GraphQL runtime errors, this will also not work with relationships

@changeset-bot

This comment was marked as resolved.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Apr 12, 2023

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 15c0e11:

Sandbox Source
@keystone-6/sandbox Configuration

@dcousens
Copy link
Member

Can you add an example to the test sandbox?

@borisno2 borisno2 requested a review from dcousens April 12, 2023 23:38
@dcousens dcousens changed the title Add GraphQL Global types to structure JSON Add a new graphql.typeName for the structure field to support deduplication of GraphQL types Apr 13, 2023
@borisno2 borisno2 force-pushed the add-global-types-to-structure branch from 8dffd03 to f00e496 Compare April 18, 2023 01:32
@borisno2 borisno2 force-pushed the add-global-types-to-structure branch from 4e857af to 15c0e11 Compare May 2, 2023 22:54
@dcousens dcousens self-assigned this Aug 1, 2023
@molomby
Copy link
Member

molomby commented Feb 26, 2024

This relates to a more general problem I've hit around GraphQL type re-usage across fields and custom mutations. Currently there's no way (that I know of; please correct me) that let's you share/reuse a GraphQL types between multiple virtual fields, nor is it possible to share a GraphQL type between a virtual fields and GraphQL extensions.

Part if the problem is that, when you need to refer to existing list types for a virtual field, you use the lists argument, eg. graphql.field({ type: lists.Post.types.output, ... }), as documented here. But if you want to do the same thing in extendGraphqlSchema you reference the base object, like this: graphql.field({ type: base.object('Post'), ... }).

In my current project we have managed to reuse types across multiple GraphQL extensions by closuring over base then passing around an object of types, but it kinda sucks. Something like this:

export const extendGraphqlSchema: ExtendGraphqlSchema = graphql.extend((base) => {
  const loaders = buildLoaders(base);
  const dynamicGqlTypes = buildDynamicGqlTypes(base, loaders);

  return {
    query: {
      dodads: dodadsQuery({ dynamicGqlTypes }),
      thingamajigs: thingamajigsQuery({ dynamicGqlTypes }),
      search: searchQuery({ base, dynamicGqlTypes }),
    },
    mutation: {
      createDodad: createDodadMutation({ dynamicGqlTypes }),
      updateDodad: updateDodadMutation({ dynamicGqlTypes }),
      createThingamajig: createThingamajigMutation({ dynamicGqlTypes }),
      updateThingamajig: updateThingamajigMutation({ dynamicGqlTypes }),
    },
  };
});

If you could lazily create and cache them like this...

let dodadGraphQLType;

function getDodadGraphQLType(base) {
  if (dodadGraphQLType) return dodadGraphQLType;
 dodadGraphQLType = graphql.object({
    name: 'DodadOutput',
    fields: {
      // ...
    },
  });
  return dodadGraphQLType;
}

Then you could just pull the types you needed into each mutation separately but this doesn't work because Keystone creates two schemas (the standard one and another for sudo operations) – you need two distinct GraphQL types (ie. the JS object describing the type) to be created so they can closure the two different base objects and reference the correct list types (which also have standard and sudo versions).

Note, even if this did work, you'd still have problems re-using the types between extensions and virtual fields because (as above) when defining virtual field types you have a lists arg but no base object – you need to abstract that difference as well.

Shouldn't Keystone have a single place we can define GraphQL types for a schema? Then developers can refer to those types by their GraphQL type names (which is always unique) when they're needed for custom queries/mutations, virtual fields, structure fields, etc. This new config (graphql.types?) wouldn't initially replace the existing places you can define GraphQL types, just supplement them.

@dcousens dcousens removed their assignment Nov 10, 2024
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.

3 participants