eddeee888 / graphql-code-generator-plugins

List of GraphQL Code Generator plugins that complements the official plugins.
MIT License
46 stars 11 forks source link

🚧 support for extend non root operations #168

Closed YutaUra closed 10 months ago

YutaUra commented 1 year ago

hi @eddeee888

It would be very useful to be able to separate interests by schema like apollo federation.

# User.graphql

type User {
  id: ID!
}
# Post.graphql

type Post {
  id: ID!
}

extend type User {
  posts: [Post!]!
}

In this case, it is like schema/post/resolvers/User/posts.ts where individual resolvers are generated.

import type { UserResolvers } from './../../../types.generated';

export const posts: NonNullable<UserResolvers['posts']> = async (
  _parent,
  _arg,
  _ctx
) => {
  /* Implement User.posts resolver logic here */
};

I described what the end result would ideally be as an e2e test, but I'm not sure how to actually write the code...

Can you give me some advices?

changeset-bot[bot] commented 1 year ago

⚠️ No Changeset found

Latest commit: 49903e00f4203abb784947dcfc7b96488193fb0b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

eddeee888 commented 1 year ago

This is a great idea @YutaUra ! I like your suggestions for generated files in the e2e tests 👍

This could be a relatively big change but I think here's what we can do to get there:

  1. Update resolvers.generated.ts file to spread the main types (This could be a separate PR)
    • I believe this can be done by updating printObjectMapping to spread the identifier name
  2. Add a handler to visitor to handle when we find a type is extended. Here's the important files:
    • visitNamedType is called here to provide consistent params to our GraphQL type handlers
    • visitor contains handlers that would trigger when certain type is met. These handlers will mutate the files in ctx.result.
    • Then, somehow add these files into the resolvers in step 1... 🤔

For now, I don't think we need to add a new config option. It should be generated by default for this improvement 🙂 (I'm working on an option soon to say which resolvers we want to generate. Your suggested option will most likely be in there)

YutaUra commented 1 year ago

Thanks for the advice! I'll check it out! :)

eddeee888 commented 1 year ago

Hi @YutaUra ! Thanks for the PRs and the description. It really helps me understand your ideas 🙌

This just occurred to me: if we treat the extended object types similar to root objects (Query, Mutation, Subscription), we cannot easily use ensureObjectTypeResolversAreGenerated function to automatically create resolvers if the mapper types don't match up.

Extending from your example above, given this schema:

# User.graphql

type User {
  id: ID!
  name: String!
}

# Post.graphql

type Post {
  id: ID!
}

extend type User {
  posts: [Post!]!
  status: String!
}

I think it could be better if we roughly generated it like this:

// schema/user/resolvers/User.ts
import type { UserResolvers } from './../../types.generated';
export const User: Pick<UserResolvers, 'id' | 'name' > = {
  // automatically generate resolvers based only on the picked fields above
};

// schema/post/resolvers/User.ts
import type { UserResolvers } from './../../types.generated';
export const User: Pick<UserResolvers, 'posts' | 'status' > = {
  // automatically generate resolvers based only on the picked fields above
};

Then, at the resolvers.generated.ts file:

import { User as user_User } from './user/resolvers/User';
import { User as post_User } from './post/resolvers/User';

export const resolvers: Resolvers = {
  // other things ...
  User: {
    ...user_User,
    ...post_User
  }
}

Keen to hear your thoughts!


This does mean the following:

eddeee888 commented 10 months ago

Hi @YutaUra 👋

Thanks to your original idea, I have a PR for this feature now: https://github.com/eddeee888/graphql-code-generator-plugins/pull/182 🕺

You can try the alpha version here:

yarn add -D @eddeee888/gcg-typescript-resolver-files@pr182-run298-1
eddeee888 commented 10 months ago

This is available in v0.7.0: https://github.com/eddeee888/graphql-code-generator-plugins/releases/tag/%40eddeee888%2Fgcg-typescript-resolver-files%400.7.0

Thanks so much for the inspiration and discussion! Please let me know if it doesn't suit your needs or any improvement ideas!

YutaUra commented 10 months ago

I'm really sorry that i could't work this PR because my job was hard last month... 🙇 And I appreciate your work which implements my idea!!

LGTM!!!

eddeee888 commented 10 months ago

Hi @YutaUra , do you have Twitter/X account? If yes, could I mention you in the v0.7 release tweet? 🙂

YutaUra commented 10 months ago

@eddeee888 Of course you do! Here's my Twitter account https://twitter.com/3594914 thank you :)