Skip to content

[typescript-resolvers] Custom field level contextType #3052

@eddeee888

Description

@eddeee888

Is your feature request related to a problem? Please describe.

I am using a directive to handle viewer authentication. This directive is attached to fields that require viewer authentication check so I don't have to do the same check in every resolver. If the viewer object does not exist in context, I throw an error.

This means by the time it gets to the resolver, the viewer in my context wouldn't be null anymore. This means the contextType interface that applies to every field does not work.

Example

# schema.graphql
type mutation {
  viewMessages(): [Message!]!
  createMessage (content: String!): Message! @isLoggedIn
}
// graphql/types.ts

// This resolver context is used for all fields
export interface ResolverContext<U = User | null> extends ExpressContext {
  viewer: U
}

// This resolver context should be used for fields with `isLoggedIn` directive
export type ResolverContextLoggedIn = ResolverContext<User>;
# codegen.yml
generates:
  ./src/graphql/resolvers/types.generated.ts:
    plugins:
      - typescript
      - typescript-resolvers
    config:
      contextType: graphql/types#ResolverContext
// types.generated.ts

export type MutationResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation']> = ResolversObject<{
  viewMessage?: Resolver<
    Array<ResolversTypes['Message']>,
    ParentType,
    ResolverContext, // This is OK here 
  >
  createMessage?: Resolver<
    ResolversTypes['Message'],
    ParentType,
    ResolverContext, // I want this to be `ResolverContextLoggedIn`
    ...
  >;
}>

Describe the solution you'd like
I would love to have a fieldContextTypes option that allows me to override the general contextType. For example:

# codegen.yml

generates:
  ./src/graphql/resolvers/types.generated.ts:
    plugins:
      - typescript
      - typescript-resolvers
    config:
      contextType: graphql/types#ResolverContext
      fieldContextTypes:
         - mutation.createMessage#graphql/types#ResolverContextLoggedIn

Describe alternatives you've considered
We could attach a directive into the schema and parse it from there...? Not sure if this is even possible. e.g.

# schema.graphql
type mutation {
  createMessage (content: String!): Message! @isLoggedIn @context("graphql/types#ResolverContextLoggedIn")
}

Additional context
If this sounds ok, I will try to create a PR for this

Metadata

Metadata

Assignees

Labels

pluginswaiting-for-releaseFixed/resolved, and waiting for the next stable release

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions