graphql-nexus / nexus-plugin-prisma

Deprecated
MIT License
828 stars 118 forks source link

Enums cannot be exposed via model #383

Closed iherger closed 5 years ago

iherger commented 5 years ago

Enums work well now both for mutations and queries.

However, the typegen still seems to be missing something.

In the definition of the field (t.model.myfield), I get the following error:

ERROR: No subset types are available. Please make sure that one of your GraphQL type is a subset of your t.model('<ModelName>')

Screenshot:

Screenshot 2019-09-03 at 07 17 45
jasonkuhrt commented 5 years ago

Thanks for reporting @iherger, could you provide a repro?

iherger commented 5 years ago

Here is a repo: https://github.com/iherger/prisma2-enum

Steps to reproduce:

git clone https://github.com/iherger/prisma2-enum.git
cd prisma2-enum
yarn install
code src/index.ts

Then you should see the error in the screenshot above.

jasonkuhrt commented 5 years ago

Able to repro easily in the example app as well.

Weakky commented 5 years ago

Hey 👋,

This error is related to #323. No subset types are available indeed, because the enum is not exposed on the schema at all. The error would go away if you declared the enum yourself with enumType, and added it to makeSchema({ types: [..] }).

We need to figure out whether we want the enums to be automatically published or not.

iherger commented 5 years ago

Thanks, @Weakky

I guess it would be great if we could use the enums that were already defined in schema.prisma.

Declaring the enum with enumType would somewhat be a duplication, if I understand this correctly.

Weakky commented 5 years ago

Yes, but you could argue the same with object types.

Right now, only input types are automatically exposed to the schema. But enums are both input and output types.

Which means that if you expose some filtering inputs and that the enum appears to be in some of the inputs, we will expose the enum.

However, if it doesn't appear in any of your input types, and you're trying to expose a field of an object type with an output type being an enum (eg: type User { gender: GENDER }), there it won't be exposed.

We could therefore always expose enums, but:

Ideally, just like in nexus-prisma v1, we would automatically expose the enum if the user did not expose it by hand. But with the new architecture, this doesn't seem possible anymore

The other approach would be to have something like t.model and t.crud to expose your enum values. But again, because enums are both input/output types, it creates inconsistencies with the rest.

iherger commented 5 years ago

I guess, something similar to t.model or t.crud would work (maybe t.enum?).

To make life easier (in certain cases), it would be great to have a method to expose all values of an enum (similar to what has been proposed for t.model or even t.crud).

iherger commented 5 years ago

Trying to define the enum with enumType doesn't seem to be possible, I get an error along the lines of PASSSTATUS was already defined and imported as a type, check the docs for extending types

So, how would you go about properly defining the enum?

jasonkuhrt commented 5 years ago

I think it makes sense to auto-publish.

What will happen if someone wants to customize that enum? (add or remove some member)

  1. User crafts own enum:
import { enumType } from 'nexus'

export const Foo = enumType({ name: "Foo", members: ["a", "b", "c"] })
  1. User customizes db schema enum:
import DBSchema from '@generated/nexus-prisma'

export const Foo = DBSchema.Enums.Foo({ omit: ["b"] })

Alternative, based on around pure functions and simple data

import R from 'ramda'
import DBSchema from '@generated/nexus-prisma'

// general idea, not actual, could imagine domain helpers, ...
export const Foo = DBSchema.Enums.Foo |> R.transform(R.pipe(select("members"), omit("b")))

Identifier name DBSchema = 🤢 but blocked on thinking of better name right now.

It creates inconsistencies with the rest. eg: why are input types automatically exposed, not output types, but enums are?

I think a still-consistent rule could be: Any GQL Type which may be in input position may get auto-published.

Weakky commented 5 years ago

The issue with users crafting their own enum is not so much how they do it, but rather the fact that with the current architecture, I'm pretty sure we have no way to know whether the user crafted its own enum or not when calling nexusPrismaPlugin(). Consequently, we'd end up with duplicate types.

We used to do have that information by wrapping the nexus SchemaBuilder, but we no longer can do that since we removed the makePrismaSchema function to simplify the surface API

One way would be to add another required property to nexusPrismaPlugin which would be the same types passed to makeSchema

jasonkuhrt commented 5 years ago

The issue with users crafting their own enum is not so much how they do it, but rather the fact that with the current architecture, I'm pretty sure we have no way to know whether the user crafted its own enum or not when calling nexusPrismaPlugin(). Consequently, we'd end up with duplicate types.

👍

One way would be to add another required property to nexusPrismaPlugin which would be the same types passed to makeSchema

As discussed on our call, I think this is a very reasonable step forward. Great idea!

We also talked about how making nexus-prisma a first-class nexus plugin could also be a solution, but longer term. Blocked by https://github.com/prisma/nexus/pull/200.

iherger commented 5 years ago

@jasonkuhrt , @Weakky

I can use enums in queries and mutations, but I can't filter on them. I am not sure if this is related to the discussion in this thread, or if I should open a new thread for this.

E.g.

{
  things(where: { status: { equals: "VALID" } }) {
    id
    name
    status
  }
}

doesn't work.

jasonkuhrt commented 5 years ago

I can use enums in queries and mutations, but I can't filter on them. I am not sure if this is related to the discussion in this thread, or if I should open a new thread for this.

@iherger Please open a new thread, and as always your great repro repos always most welcome 😄(we're working on putting together integration tests this sprint which should reduce our resorting to such archaisms).

shoaibsharif commented 5 years ago

Did you find a solution? I still get a problem and I get this error:

src/resolvers/User.ts:13:13 - error TS2554: Expected 1 arguments, but got 0.

13     t.model.gender();
               ~~~~~~~~

  node_modules/@generated/nexus-prisma/index.d.ts:129:7
    129       opts: NexusPrismaRelationOpts<ModelName, MethodName, ReturnType>
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    An argument for 'opts' was not provided.

Do you want me to create a new issue?

jasonkuhrt commented 5 years ago

@shoaibsharif we haven't cut a release, soon. I don't know if you're issue is related to this one though.

shoaibsharif commented 5 years ago

I think it does. I have this problem when I try to expose enum via model in User. For example: Screen Shot 2019-09-22 at 5 38 31 PM In the picture it is giving me the same error, but it shows in my schema.graphql. It is giving me that error and my server is not running. Note that, I just figure it out right now, if I run my server with --transpileOnly and if I use only one t.crud in Mutation, it still gives me red underline on t.model.gender(), but it is not giving me any issue. When I use t.crud in Mutation and if it sees that I have defined gender enums, it doesn't like that. it gives me this error:

GENDERS was already defined and imported as a type, check the docs for extending types

That I found really weird.

jasonkuhrt commented 5 years ago

@shoaibsharif thanks for the clarification, yeah this issue should be fixed on the next release.

abdusamadtv commented 5 years ago

@jasonkuhrt could you clarify please? because I'm still getting this error

prisma version 2.0.0-preview-13.2 nexus version 0.12.0-beta.9

image

jasonkuhrt commented 5 years ago

@AbdusamadTurdiev What version of nexus-prisma are you using? See the example in this repo if you haven't already.

abdusamadtv commented 5 years ago

@AbdusamadTurdiev What version of nexus-prisma are you using? See the example in this repo if you haven't already.

I couldn't find nexus-prisma in project's package-lock.json and also there's no package-lock.json in global prisma2 folder

jasonkuhrt commented 5 years ago

Hey @AbdusamadTurdiev I'm referring to this example https://github.com/prisma-labs/nexus-prisma/tree/master/examples/blog. Find me on slack if it would be faster for you.

mikeslade commented 5 years ago

@jasonkuhrt I am seeing the same behavior as @AbdusamadTurdiev

nexus-prisma@0.4.2

Using the example that you provided in the last comment, update the schema.prisma model. Add new enum PostType and apply to the Post model:

model Post {
  id    Int      @id
  title String
  tags  String[]
  blog  Blog
  type  PostType
}

enum PostType {
  BORING
  AWESOME
}

Run yarn generate

Then update your Post.ts file under src>schema to add the new "type" field:

import { objectType } from 'nexus'

export const Post = objectType({
  name: 'CustomPost',
  definition(t) {
    t.model('Post').id()
    t.model('Post').title()
    t.model('Post').tags()
    t.model('Post').type()
  },
})

You will see that it still has the error: image

(property) type: (opts: {
    alias?: string | undefined;
} & {
    type: "ERROR: No subset types are available. Please make sure that one of your GraphQL type is a subset of your t.model('<ModelName>')";
}) => NexusPrismaFields<...>
Expected 1 arguments, but got 0.ts(2554)
index.d.ts(129, 7): An argument for 'opts' was not provided.

If you run yarn dev, everything runs without issue...

jasonkuhrt commented 5 years ago

Hey @mikeslade, thanks for the repro steps. I was able to follow and indeed something seems fishy. I will debug more Thursday/Friday.

mikeslade commented 5 years ago

@jasonkuhrt I am also seeing the exact same error with t.crud.updateMany*. Not sure if the issue is somehow related.

So, update Mutation.ts with: image

The error is the same and the functionality works without issue when running yarn dev (after adding the missing type noted here: https://github.com/prisma-labs/nexus-prisma/issues/341#issuecomment-531764695)

jasonkuhrt commented 5 years ago

I have narrowed the issue down to typegen. The runtime is ok, operations can be made successfully against enums.

jasonkuhrt commented 5 years ago

We determined that this issue is indeed resolved and that it was another issue leading to the most recent rash of problems.

nhuesmann commented 4 years ago

@jasonkuhrt I just ran into this issue. I'm getting the following error when I try to expose and enum field on a model: type: "ERROR: No subset types are available. Please make sure that one of your GraphQL type is a subset of your t.model('<ModelName>')";

I'm using the following package versions:

"@prisma/photon": "2.0.0-preview019",
"nexus": "0.12.0-rc.5",
"nexus-prisma": "0.6.1",
"prisma2": "2.0.0-preview019",

Are there any quick steps I can try in order to resolve this, or would you like me to create a testable repo?

jasonkuhrt commented 4 years ago

@nhuesmann could you try a repro with graphql-santa. It brings things together and controls integration. Faster for you too.

nhuesmann commented 4 years ago

@jasonkuhrt I went ahead and tried reproducing with graphql-santa—issue didn't occur. I'm not sure what I should do to move forward though since you stated that santa isn't ready for serious use. Is there a way I can get this to work in my current app? I'm using prisma2 + nexus + yoga.

Also, what are the plans for santa? I have had definitely had issues trying to get prisma2, nexus, and yoga config to work nicely together as they're all heavily in development (nexus.ts isn't always generated, typescript often complains about nexus, restarts take a long time). I also have found myself frequently scouring forums / GH issues / slack to find out how to get things working. If santa is the next step for the graphql/prisma/nexus ecosystem, say the word and I'll invest some time into working with it. It'd be awesome if there was a create-react-app/expo-esque framework for prisma + nexus backends. Thanks!

-EDIT: I messaged you on the prisma slack, feel free to answer there if it feels more fitting than on this GH issue.

jasonkuhrt commented 4 years ago

Hey @nhuesmann while these libraries are key and will continue to improve we envision that santa is the entry point for most users. Of course users will always be free to assemble the libraries themselves how they see fit, but that will also mean taking on the integration work.

If you can invest into santa and give us feedback on issues you hit we’d heartily welcome that. Our quarter is focused on it and your needs can help shape its roadmap and priorities.

Sent with GitHawk

nhuesmann commented 4 years ago

@jasonkuhrt thanks for the reply and explanation, I will put some effort into trying it out with my current app and see if I run into any issues!

seed-of-apricot commented 4 years ago

Did you get any update on this?

homerjam commented 4 years ago

This error still seems to come up for me (nexus@0.12.0 / nexus-prisma@0.12.0). Was there a solution?

AnatoleLucet commented 4 years ago

@homerjam it seems like restarting the dev script worked for me. Ctrl + C then yarn dev / npm run dev

fullStackDataSolutions commented 3 years ago

I'm getting the following errors from Enums with MySQL,

"message": "\nInvalidprisma.ftp_profile.findMany()invocation:\n\n\n Value '' not found in enum 'DatabaseEnumType { name: \"ftp_profile_server_protocol\", internal_enum: InternalEnum { name: \"ftp_profile_server_protocol\", values: [InternalEnumValue { name: \"FTP\", database_name: None }, InternalEnumValue { name: \"SFTP\", database_name: None }, InternalEnumValue { name: \"FTPS\", database_name: None }] } }'"

"@prisma/client": "^2.14.0", "nexus": "^1.0.0", "nexus-plugin-prisma": "^0.28.0", "@prisma/cli": "^2.14.0",

I've tried manually creating the enums, and many other solutions, and no matter what I get an error message.

oscar-gallog commented 2 years ago

So? there is no solution to this?