graphql-code-generator icon indicating copy to clipboard operation
graphql-code-generator copied to clipboard

feat: override operation field types via directives

Open izumin5210 opened this issue 3 years ago • 5 comments

Description

Add directiveFieldMappings option to typescript-operations plugin to overriding operation field types via directives.

Related https://github.com/dotansimha/graphql-code-generator/issues/7356

I fixed @jenseng's implementation to follow master and pass tests.

Example

# codegen.yml
plugins:
  config:
    # You cannot control optional(`?`) with `directiveFieldMapping`.
    # Setting `avoidOptionals` is recommended when defining directives that change nullability, such as `@nonNull` or `@required`.
    avoidOptionals:
      field: true  #
    directiveFieldMappings:
      asString: AsStringTransform
      nonNull: NonNullable
      nonNullEntries:
        type: NonNullable
        entries: true
# GraphQL Schema
directive @asString on FIELD
directive @nonNull on FIELD
directive @nonNullEntries on FIELD
                                         
type User {
  id: Int
  username: String
  emails: [String]
}
                                         
...
# GrpahQL operation document
query {
  me {
    id @asString @nonNull
    username @nonNull
    emails @nonNullEntries
  }
}
// generated type
{
  me: {
    id: AsStringTransform<number>,
    username: NonNullable<string | null>,
    emails: Array<NonNullable<string | null>> | null,
  }  
}

Type of change

Please delete options that are not relevant.

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [ ] This change requires a documentation update

Checklist:

  • [x] I have followed the CONTRIBUTING doc and the style guidelines of this project
  • [x] I have performed a self-review of my own code
  • [x] I have commented my code, particularly in hard-to-understand areas
  • [x] I have made corresponding changes to the documentation
  • [x] My changes generate no new warnings
  • [x] I have added tests that prove my fix is effective or that my feature works
  • [x] New and existing unit tests pass locally with my changes
  • [x] Any dependent changes have been merged and published in downstream modules

Further comments

  • directive argument support is not included in the first release
    • e.g. @required(entries: true), @as(type: "boolean")
    • Because:
      • the need to discuss the optimal configuration file design
      • even if arguments are not supported, the minimum use case can be satisfied
      • it can be implement later without breaking changes

izumin5210 avatar Jul 09 '22 09:07 izumin5210

🦋 Changeset detected

Latest commit: eea74b2d67b41c22f8578169826d031441f2128c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 39 packages
Name Type
@graphql-codegen/visitor-plugin-common Minor
@graphql-codegen/typescript-operations Minor
@graphql-codegen/flow Patch
@graphql-codegen/flow-operations Patch
@graphql-codegen/flow-resolvers Patch
@graphql-codegen/java-apollo-android Patch
@graphql-codegen/java-common Patch
@graphql-codegen/java Patch
@graphql-codegen/kotlin Patch
@graphql-codegen/java-resolvers Patch
@graphql-codegen/typescript-apollo-angular Patch
@graphql-codegen/typescript-apollo-client-helpers Patch
@graphql-codegen/typescript-document-nodes Patch
@graphql-codegen/typescript-generic-sdk Patch
@graphql-codegen/gql-tag-operations Patch
@graphql-codegen/typescript-graphql-request Patch
@graphql-codegen/typescript-jit-sdk Patch
@graphql-codegen/typescript-mongodb Patch
@graphql-codegen/typescript-msw Patch
@graphql-codegen/typescript-oclif Patch
@graphql-codegen/typescript-react-offix Patch
@graphql-codegen/typescript-react-apollo Patch
@graphql-codegen/typescript-react-query Patch
@graphql-codegen/typescript-resolvers Patch
@graphql-codegen/typescript-rtk-query Patch
@graphql-codegen/typescript-stencil-apollo Patch
@graphql-codegen/typescript-type-graphql Patch
@graphql-codegen/typed-document-node Patch
@graphql-codegen/typescript Patch
@graphql-codegen/typescript-urql-graphcache Patch
@graphql-codegen/urql-svelte-operations-store Patch
@graphql-codegen/typescript-urql Patch
@graphql-codegen/typescript-vue-apollo-smart-ops Patch
@graphql-codegen/typescript-vue-apollo Patch
@graphql-codegen/typescript-vue-urql Patch
@graphql-codegen/jsdoc Patch
@graphql-codegen/graphql-modules-preset Patch
@graphql-codegen/import-types-preset Patch
@graphql-codegen/near-operation-file-preset Patch

Not sure what this means? Click here to learn what changesets are.

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

changeset-bot[bot] avatar Jul 09 '22 09:07 changeset-bot[bot]

@izumin5210 is attempting to deploy a commit to the The Guild Team on Vercel.

A member of the Team first needs to authorize it.

vercel[bot] avatar Jul 09 '22 09:07 vercel[bot]

I wonder whether it instead would make sense that the field types are wrapped within a generic. That would allow more flexibility as well as allow chain ability of directives.

plugins:
  config:
    directiveFieldMappings:
      asString: type AsStringTransform<_TIn> = string
      nonNull: type NonNullTransform<TIn> = Exclude<TIn, null | undefined>
      asBoolean: type AsBooleanTransform<_TIn> = boolean
query MeQuery {
	me {
		id @asBoolean @asString
	}
}
type AsBooleanTransform<_TIn> = boolean

type Me = {
	__typename?: 'User';
	id: AsString<AsBooleanTransform<boolean>>;
};

n1ru4l avatar Jul 12 '22 07:07 n1ru4l

Sorry for the delay in replying :bow:

I wonder whether it instead would make sense that the field types are wrapped within a generic. That would allow more flexibility as well as allow chain ability of directives.

I too think that is a great idea! I will update this pull request or create a new one!

izumin5210 avatar Jul 31 '22 07:07 izumin5210

I updated the codes and PR description! could you review them? :pray:

izumin5210 avatar Jul 31 '22 12:07 izumin5210

We talked about this a lot and came to the conclusion that this is an anti-pattern. If you want special handling for a field you should use a custom scalar instead. See https://github.com/dotansimha/graphql-code-generator/issues/1532

I am going to close this.

n1ru4l avatar Mar 16 '23 14:03 n1ru4l