Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Enum handling #213

Closed
affanshahid opened this issue Oct 28, 2018 · 27 comments
Closed

Enum handling #213

affanshahid opened this issue Oct 28, 2018 · 27 comments

Comments

@affanshahid
Copy link

If I add an enum to my gql schema with a matching enum in my models file, the tool throws an error saying a model was not found. If I change the type of the enum (in my models) to interface, then it works but obviously is broken.

TL;DR: The tool expects an interface model for an enum in the schema

@Weakky
Copy link
Contributor

Weakky commented Oct 29, 2018

Hey 👋,

We're indeed currently not supporting enums defined in typescript files.

One current workaround would be to define your enums using union types based on string literals instead of TS interfaces.

Given such an enum defined in your GraphQL schema:

enum Color {
  RED,
  GREEN,
  BLUE
}

You could define such a type in your typescript file:
(Which is not perfect but better than an using an interface)

type Color = 'RED' | 'GREEN' | 'BLUE'

Bottom line: This is a known limitation that we'll have to fix 🙏

@affanshahid
Copy link
Author

Thanks for the help! This excellent tool btw, great work.

@arielschiavoni
Copy link

arielschiavoni commented Oct 29, 2018

Hi, I have a very similar issue. I use the config from the typescript-graphql
prisma examples.

In order to make my resolver typecheck I have to use the following config defaultName: '${typeName}Node' in my graphqlgen.yml file.

models:
  files:
    - path: ./src/generated/prisma-client
      defaultName: '${typeName}Node'

Without defaultName: '${typeName}Node'

image

With defaultName: '${typeName}Node'

image

So far so good, however when I added enums to my schema I couldn't manage to make it work anymore.

The enum types are correctly generated by prisma.

schema.graphql

enum LANG {
  EN
  DE
}

prisma-client/index.ts

export type LANG = "EN" | "DE";

However I get the error that the types are not defined.

image

I tried copy pasting the union type from the prisma-client/index.ts file into my own models.ts and added them to the graphqlgen config without the defaultName prop. But it does not work either.

models:
  files:
    - path: ./src/generated/prisma-client
      defaultName: '${typeName}Node'
    - path: ./src/models.ts

@sidroopdaska
Copy link

Is there a timeline on this being fixed?

@Weakky
Copy link
Contributor

Weakky commented Oct 30, 2018

Hey 👋,

The reason for this behavior at the moment is because of the defaultName: '${typeName}Node' property. Enums generated by prisma-client do not have this pattern name and are therefore ignored. Although this is technically not a bug, we need to find a way make this clearer and simpler.

Workaround

Suggestion 1

Configure your models property of your graphqlgen.yml file in the following way:

models:
  files:
    - ./src/generated/prisma-client
    - path: ./src/generated/prisma-client
      defaultName: '${typeName}Node'

This way, graphqlgen is going to proceed like this:

  • Look for typescript models that have the same names as your graphql types (eg: Role model mapping to Role graphql type)
  • If none found, look for typescript models that matches graphql type names following the pattern ${typeName}Node (eg: UserNode model mapping to User graphql type).

Suggestion 2

Configure your models property of your graphqlgen.yml file in the following way:

models:
  files:
    - path: ./src/generated/prisma-client
      defaultName: '${typeName}Node'
  override:
    graphqlEnumName: ./src/generated/prisma-client:modelName

The override property allows you to define a mapping between a graphql type and a model, in case you're using some special convention for some types.
You could also use this property so enumerate all your enums, that doesn't follow the ${typeName}Node pattern.

@sidroopdaska
Copy link

So I could handle Enums as an edge case to this by doing the following:

IN schema.graphql

enum SessionType {
    Control,
    Perception
}

In my ts types, I do:

export const enum SessionTypeEnum { ... }

and add the defaultName as ${typeName}Enum

Also, how can I handle custom scalars like scalar Date ?

@Weakky
Copy link
Contributor

Weakky commented Oct 30, 2018

You could indeed do that or look at the second suggestion I shared after editing the comment.

For scalars, please take a look at #165 but do not cross issues and topics so that we can keep discussions clean 🙏

@Weakky
Copy link
Contributor

Weakky commented Nov 2, 2018

Update

We decided to give enums a special treatment. Enum types will always be inferred from your GraphQL schema, and will be inlined automatically in your graphqlgen.ts file.

For instance, given the following graphql schema:

type User {
  penColor: Color!
}

enum Color {
 RED,
 GREEN,
 BLUE 
}

Your graphqlgen.ts file should roughly look like this:

import { User } from '../types.ts'

type Color = 'RED' | 'GREEN' | 'BLUE'

export type PenColorResolver = (
  parent: User,
  args: {},
  ctx: any,
  info: GraphQLResolveInfo,
) => Color | Promise<Color>

@sidroopdaska
Copy link

When will this update be released?

@schickling
Copy link
Contributor

I've released a first version which can be installed via graphqlgen@beta. Please report if you run into any problems 🙏

@impowski
Copy link

impowski commented Nov 5, 2018

I've released a first version which can be installed via graphqlgen@beta. Please report if you run into any problems 🙏

Just installed it and ran graphqlgen

internal/modules/cjs/loader.js:589
    throw err;
    ^

Error: Cannot find module '@babel/types'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:587:15)
    at Function.Module._load (internal/modules/cjs/loader.js:513:25)
    at Module.require (internal/modules/cjs/loader.js:643:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/Users/impowski/.config/yarn/global/node_modules/graphqlgen/dist/introspection/ts-ast.js:15:15)
    at Module._compile (internal/modules/cjs/loader.js:707:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:718:10)
    at Module.load (internal/modules/cjs/loader.js:605:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:544:12)
    at Function.Module._load (internal/modules/cjs/loader.js:536:3)

@Victorkangsh
Copy link

@impowski npm i -g @babel/types

@impowski
Copy link

impowski commented Nov 5, 2018

@impowski npm i -g @babel/types

@Victorkangsh I guess I should not do that :)

@schickling
Copy link
Contributor

Please retry with [email protected]

@impowski
Copy link

impowski commented Nov 5, 2018

Please retry with [email protected]

@schickling Can you give a sample example of what it should look like?

Right now I have something like that in my datamodel.graphql:

type User {
  gender: Gender!
}

enum Gender {
  NONE
  MALE
  FEMALE
}

And inside schema.graphql I have this:

type User {
  gender: Gender!
}

When I run graphqlgen it gives me this:

Error occurred while reading schema: Error: Field gender: Couldn't find type Gender in any of the schemas.

When I add to my schema.graphql this:

enum Gender {
  NONE,
  MALE,
  FEMALE
}

I receive this output:

WARNING: Unsupported type TSIntersectionType (Line 10 in /Users/impowski/Projects/heart-advisor-server/src/generated/prisma-client/index.ts). Please file an issue at https://github.com/prisma/graphqlgen/issues
WARNING: Unsupported type TSFunctionType (Line 14 in /Users/impowski/Projects/heart-advisor-server/src/generated/prisma-client/index.ts). Please filean issue at https://github.com/prisma/graphqlgen/issues
WARNING: Unsupported type TSIntersectionType (Line 19 in /Users/impowski/Projects/heart-advisor-server/src/generated/prisma-client/index.ts). Please file an issue at https://github.com/prisma/graphqlgen/issues
(node:63709) UnhandledPromiseRejectionWarning: Error: Unsupported notation for fields: Line 22 in /Users/impowski/Projects/heart-advisor-server/src/generated/prisma-client/index.ts
    at throwIfUnsupportedFields (/Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/ts-ast.js:100:15)
    at extractInterfaceFields (/Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/ts-ast.js:106:5)
    at extractInterface (/Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/ts-ast.js:118:27)
    at /Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/ts-ast.js:163:59
    at Array.reduce (<anonymous>)
    at Object.buildTSTypesMap (/Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/ts-ast.js:154:45)
    at buildTypesMapByLanguage (/Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/index.js:21:29)
    at buildTypesMap (/Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/index.js:31:20)
    at /Users/impowski/Projects/heart-advisor-server/node_modules/graphqlgen/dist/introspection/index.js:44:60
    at Array.reduce (<anonymous>)
(node:63709) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:63709) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@Weakky
Copy link
Contributor

Weakky commented Nov 5, 2018

Oh, good that we put it in beta first. I didn't think about testing it with prisma-client, which uses quite a few special types. These are:

export interface Fragmentable {
  $fragment<T>(fragment: string | DocumentNode): Promise<T>; // <--- This
}

and this (admittedly less special)

views: (where?: ViewsWhereInput) => Promise<boolean>; // <--- This

I see a few things here:

  • As you might have guessed, FunctionType and IntersectionType not yet handled, which is the reason for these warnings

  • I'm not sure how to proceed with these warnings. They're super relevant if we want to progressively support more and more language syntaxes and have people reporting us there use-cases. But at the same time, they're super cumbersome especially considering the fact that you're supposed to run graphqlgen quite often.

  • Lastly, I'm gonna add support for these types and will come back to you as soon as it's done 🙏

@Weakky
Copy link
Contributor

Weakky commented Nov 5, 2018

We just released [email protected] which should fix your issues @impowski.

To answer a bit more your previous question, this is how it is supposed to be done:

Given the following GraphQL schema:

type User {
  gender: Gender!
}

enum Gender {
  FEMALE
  MALE
}

The field gender of your model can have whatever type you want, but if you want it go be generated within the defaultResolvers, then the type of gender must be either equal to the GraphQL enum Gender, or be a subset of it.

eg:

interface User {
  gender: Gender
}

// Will go to defaultResolvers
enum Gender {
  FEMALE,
  MALE
}

//or
enum Gender { // Will go to defaultResolvers
  MALE
}

// or
type Gender = 'FEMALE' | 'MALE' // Will go to defaultResolvers

// or
interface User {
  gender: 'FEMALE' | 'MALE' // Will go to defaultResolvers
}

//or
enum Gender { // Will NOT got to defaultResolvers
  NONE,
  MALE,
  FEMALE
}

@impowski
Copy link

impowski commented Nov 5, 2018

@Weakky yep, that works, but should I always add types to schema.graphql? Because before that with codegen there was no need to do such thing as I remember it was importing types from prisma,graphql generated file. If I don't add anything it gives a error but when I add it it works fine.

@Weakky
Copy link
Contributor

Weakky commented Nov 5, 2018

Unless I don't understand what you mean, there are no way for us not to make you declare your enums in your GraphQL schema. The error you're getting comes from graphql-js:parse() function, which yells at you because it cannot find the type of one of your fields.

Instead of redeclaring your enum by hand, what you can do is to import the enum from the GraphQL schema generated by prisma.

This can be done using graphql-import, which is supported by graphqlgen

# import YourEnum from "path-to-your-generated-prisma-schema"

type User {
  enum: YourEnum!
}

@victory1908
Copy link

Looking forward to proper enum handling in the next release of graphqlgen. Could make a simple example of project which handling of enum combine with prisma client (Or just graphQL file + graphqlgen.yml). Thanks

@impowski
Copy link

impowski commented Nov 6, 2018

@Weakky This is what I meant

# import YourEnum from "path-to-your-generated-prisma-schema"

How do I get this generated schema file?

@schickling
Copy link
Contributor

It's now released in version 0.3.0.

@gustawdaniel
Copy link

How about enum in prisma 2.0? Any docs?

@Rydez
Copy link

Rydez commented Sep 19, 2020

@gustawdaniel Did you end up getting this to work with prisma 2?

My graphql schema has:

enum Category {
  bug
  feature
}

type Thread {
  category: Category!
}

which ends up as this in the generated file:

export enum Category {
  Bug = 'bug',
  Feature = 'feature'
}

In prisma schema I have:

enum category_enum {
  bug
  feature
}

Which results with this error in my resolvers:
Type '"bug" | "feature"' is not assignable to type 'Category'

@zakthedev
Copy link

@Rydez did you solve this?

@mdurakovic
Copy link

@Rydez do you have solution for this? I have same issue as you 😞

@Rydez
Copy link

Rydez commented Nov 9, 2020

@zakthedev, @mdurakovic, I took a look at the project I was working on at the time, and I switched to this:

type Thread {
  ...
  category: String! # Why not Category? https://github.com/prisma-labs/graphqlgen/issues/213
  ...
}

instead of this:

type Thread {
  ...
  category: Category!
  ...
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests