Joshua Richardson
Joshua Richardson

Reputation: 115

Enum mismatch between typescript and graphql-codegen

I'm currently trying to wrap my head around the below issue, and not getting very far. Currently, I'm running an Apollo-Server as my graphQL server, have prisma2 configured with a postgres database, and am utilizing graphql-codegen to generate the types from my schema. Currently, I'm trying to update a model that has a many-to-many relationship and getting really strange typescript errors being thrown. I'm pretty sure I'm doing the update incorrectly, but the errors I'm seeing aren't helpful.

The following is the pertinent code snippets:

prisma.schema

model Permission {
  id       Int             @id @default(autoincrement())
  verb     PermissionVerb
  resource PermissionModel
  own      Boolean         @default(true)
  roles    Role[]
}
    
model Role {
  id          Int          @id @default(autoincrement())
  name        String
  permissions Permission[]
}

enum PermissionModel {
  USER
  ORDER
  CUSTOMER
  PERMISSION
  ROLE
}

enum PermissionVerb {
  CREATE
  READ
  UPDATE
  DELETE
}

permission.gql

extend type Mutation {
  updatePermission(input: UpdatePermissionInput): PermissionResult!
}

union PermissionResult = Permission | PermRoleNotFoundError

type Permission {
  id: Int!
  own: Boolean
  resource: PermissionModel!
  verb: PermissionVerb!
  roles: [Role]
}

type Role {
  id: Int!
  name: String!
  permissions: [Permission]
}

type PermRoleNotFoundError {
  message: String!
}

enum PermissionModel {
  USER
  ORDER
  CUSTOMER
  PERMISSION
  ROLE
}

enum PermissionVerb {
  CREATE
  READ
  UPDATE
  DELETE
}

and finally the offending code in the resolver:

updatePermission.ts

export const updatePermission: Resolver<
  ResolversTypes['UpdatePermissionInput'],
  {},
  Context,
  RequireFields<MutationUpdatePermissionArgs, never>
> = async (_parent, args, context, _info) => {
  const { id, verb, resource, own } = args.input

  const oldPermission = await context.prisma.permission.findFirst({
    where: { id },
    include: { roles: true }
  })

  const newPermission = await context.prisma.permission.update({
    where: { id },
    data: {
      id: oldPermission.id,
      verb: verb ? verb : oldPermission.verb,
      resource: resource ? resource : oldPermission.resource,
      own: own ? own : oldPermission.own,
    },
  })

  return newPermission
}

I'm getting the following typescript warning:

Type '(_parent: {}, args: RequireFields<MutationUpdatePermissionArgs, never>, context: Context, _info: GraphQLResolveInfo) => Promise<...>' is not assignable to type 'Resolver<UpdatePermissionInput, {}, Context, RequireFields<MutationUpdatePermissionArgs, never>>'.
Type '(_parent: {}, args: RequireFields<MutationUpdatePermissionArgs, never>, context: Context, _info: GraphQLResolveInfo) => Promise<...>' is not assignable to type 'ResolverFn<UpdatePermissionInput, {}, Context, RequireFields<MutationUpdatePermissionArgs, never>>'.
Type 'Promise<Permission>' is not assignable to type 'UpdatePermissionInput | Promise<UpdatePermissionInput>'.
Type 'Promise<Permission>' is not assignable to type 'Promise<UpdatePermissionInput>'.
Type 'Permission' is not assignable to type 'UpdatePermissionInput'.
Types of property 'verb' are incompatible.
Type 'import(\"/Users/jrichardson/Documents/Projects/wsw/node_modules/.prisma/client/index\").PermissionVerb' is not assignable to type 'import(\"/Users/jrichardson/Documents/Projects/wsw/backend/src/generated/graphql\").PermissionVerb'.
Type '\"CREATE\"' is not assignable to type 'PermissionVerb'.

I don't understand why it thinks the PermissionVerb is not assignable - as from what I can see from .prisma/client/index and the generated/graphql, both enums are identical. Not sure what I'm missing here.

Any help would be greatly appreciated! Thanks

Upvotes: 2

Views: 3905

Answers (3)

Amir
Amir

Reputation: 4770

For anyone coming to this question in 2024, I just ran into the same issue. I'm using this in my project:

"prisma": "^5.9.1"

"@graphql-codegen/cli": "^5.0.2",

"typescript": "^5.3.3"

And for me, the config that actually worked was enumsAsTypes: true not constEnums: true

Here is my config:

import { type CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
  overwrite: true,
  schema: ['./schema/**/types.graphql', './schema/**/queries.graphql', './schema/**/mutations.graphql'],
  documents: ['./api/queries/**/**.ts', './api/mutations/**/**.ts'],

  generates: {
    '../../../web/src/graphql/': {
      preset: 'client',
    },

    './schema.graphql': {
      plugins: ['schema-ast'],
    },

    './types/schema.ts': {
      plugins: ['typescript'],
      config: {
        enumsAsTypes: true,
      },
    },
  },
  hooks: { afterAllFileWrite: ['prettier --write'] },
}

export default config

Upvotes: 1

Benny67b
Benny67b

Reputation: 557

You can also tell graphql-codegen to create enums as const (string unions) by setting this in codegen.yml:

config:
  enumsAsConst: true

Upvotes: 12

zodman
zodman

Reputation: 40

the prisma enum not assignable to the graphql enum .. thats the problem

Cast the return by the type of the graphql..

import { Permission  as PermissionQL  } from "../../generated/graphql";
...
return newPermission as PermissionQL;

In that way I solve the same problem.

Upvotes: -3

Related Questions