2

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

3 Answers 3

12

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

config:
  enumsAsConst: true
Sign up to request clarification or add additional context in comments.

Comments

3

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

Comments

-3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.