nexus-prisma icon indicating copy to clipboard operation
nexus-prisma copied to clipboard

"Prisma model does not have a findUnique method available" error using t.field relation

Open marceloverdijk opened this issue 2 years ago • 2 comments

Hi,

I have a Prisma model named Constructor which gave some problems in the past already as I cannot simply do prisma.constructor.findUnique({..}) because constructor here does not lead to the Prisma model..

I've worked around it by using prisma['Constructor'].findUnique({..}) and luckily this works; see below my Nexus Query type definition:

    queryType({
      definition(t) {

        t.field('constructor', {
          type: Constructor.$name,
          args: {
            id: nonNull(stringArg()),
          },
          resolve: (_parent, args, ctx) => {
            return ctx.prisma['Constructor'].findUnique({
              where: { id: args.id },
            })
          },
        })

        t.nonNull.list.nonNull.field('constructors', {
          type: Constructor.$name,
          resolve: (_parent, _args, ctx) => {
            return ctx.prisma['Constructor'].findMany({
              orderBy: {
                name: 'asc',
              },
            })
          },
        })

As I said this work and I can access both the constructor and constructors fields from GraphQL like:

query Constructor {
  constructor(id: "williams") {
    name
  }
}

Where it stops working is when I want to query relations on the Constructor model...

query Constructor {
  constructor(id: "williams") {
    name
    country {
      name
    }
  }
}

this is Nexus object definition:

objectType({
      name: Constructor.$name,
      definition(t) {
        t.field(Constructor.id)
        t.field(Constructor.name)
        t.field(Constructor.country)

and inside Prisma schema:

model Constructor {
  id         String   @map("id") @id
  name       String   @map("name")
  countryId  String   @map("country_id")
  country    Country  @relation(name: "ConstructorsByCountry", fields: [countryId], references: [id])

then I get the error:

{
  "errors": [
    {
      "message": "The prisma model Constructor does not have a findUnique method available.",
      "locations": [
        {
          "line": 4,
          "column": 5
        }
      ],
      "path": [
        "constructor",
        "country"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: The prisma model Constructor does not have a findUnique method available.",
            "    at /workspace/my-project/node_modules/nexus-prisma/dist-cjs/generator/models/javascript.js:198:19",
            "    at field.resolve (/workspace/my-project/node_modules/apollo-server-core/dist/utils/schemaInstrumentation.js:56:26)",
            "    at executeField (/workspace/my-project/node_modules/graphql/execution/execute.js:479:20)",
            "    at executeFields (/workspace/my-project/node_modules/graphql/execution/execute.js:411:20)",
            "    at completeObjectValue (/workspace/my-project/node_modules/graphql/execution/execute.js:906:10)",
            "    at completeValue (/workspace/my-project/node_modules/graphql/execution/execute.js:633:12)",
            "    at /workspace/my-project/node_modules/graphql/execution/execute.js:484:9",
            "    at async Promise.all (index 0)",
            "    at async execute (/workspace/my-project/node_modules/apollo-server-core/dist/requestPipeline.js:205:20)",
            "    at async processGraphQLRequest (/workspace/my-project/node_modules/apollo-server-core/dist/requestPipeline.js:148:28)"
          ]
        }
      }
    }
  ],

I guess it's related to issues I had myself earlier when accessing prisma.constructor.findUnique({..}) directly... instead of prisma['Constructor'].findUnique({..})...

How does the Nexus Prisma plugin access the models and could this something that gets fixed in the plugin? Or is there maybe a workaround I can implement myself?

marceloverdijk avatar Apr 03 '22 07:04 marceloverdijk

At least I can do the following workaround by resolving the relation manually:

    objectType({
      name: Constructor.$name,
      definition(t) {
        t.field(Constructor.id)
        t.field(Constructor.name)
        // https://github.com/prisma/nexus-prisma/issues/201
        // t.field(Constructor.country)
        t.field({
          ...Constructor.country,
          async resolve(parent, _args, ctx) {
            const c = await ctx.prisma['Constructor'].findUnique({
              where: { id: parent.id },
              include: {
                country: true,
              },
            })
            return c.country
          },
        })

As my Constructor model has dozens of relations this is not desired but I think I can at least workaround it...

marceloverdijk avatar Apr 03 '22 07:04 marceloverdijk

Maybe quite nasty, but this seems to works as well:

const prisma = global.prisma || new PrismaClient()

// @ts-ignore
prisma.constructor = prisma.Constructor

marceloverdijk avatar Apr 05 '22 05:04 marceloverdijk