Repository: prisma/prisma-client-js

Issue #288: The findOne throws RecordDoesNotExist in alpha.282
Created: 2019-11-06T09:14:56Z
It should not throw such an error since preview v015. BTW in v015 it was working fine.

Duplicate issue #291: Why is there a null return type if throws?
Created: 2019-11-07T19:30:18Z
Given this model:
model Blog {
  id        Int      @id
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  name      String
  viewCount Int      @default(0)
  posts     Post[]
  authors   User[]
}

And this field resolver:
    t.field('blog', {
      type: 'Blog',
      args: { id: intArg({ required: true }) },
      resolve(_root, args, ctx) {
        return ctx.photon.blogs.findOne({ where: { id: args.id } })
      },
    })
I get a TS type error because resolve return type is not satisfied by photon return type:
Type '(_root: {}, args: { id: number; }, ctx: Context) => BlogClient<Blog | null>' is not assignable to type 'FieldResolver<"Query", "blog">'.
  Type 'BlogClient<Blog | null>' is not assignable to type 'Blog | PromiseLike<Blog> | { id: MaybePromise<number>; createdAt: MaybePromise<Date>; updatedAt: MaybePromise<Date>; name: MaybePromise<string>; viewCount: MaybePromise<number>; } | PromiseLike<...>'.
    Type 'BlogClient<Blog | null>' is not assignable to type 'PromiseLike<Blog | { id: MaybePromise<number>; createdAt: MaybePromise<Date>; updatedAt: MaybePromise<Date>; name: MaybePromise<string>; viewCount: MaybePromise<number>; }>'.
      Types of property 'then' are incompatible.
        Type '<TResult1 = Blog | null, TResult2 = never>(onfulfilled?: ((value: Blog | null) => TResult1 | Promise<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | Promise<TResult2>) | null | undefined) => Promise<...>' is not assignable to type '<TResult1 = Blog | { id: MaybePromise<number>; createdAt: MaybePromise<Date>; updatedAt: MaybePromise<Date>; name: MaybePromise<string>; viewCount: MaybePromise<number>; }, TResult2 = never>(onfulfilled?: ((value: Blog | { ...; }) => TResult1 | PromiseLike<...>) | null | undefined, onrejected?: ((reason: any) => TRe...'.
          Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
            Types of parameters 'value' and 'value' are incompatible.
              Type 'Blog | null' is not assignable to type 'Blog | { id: MaybePromise<number>; createdAt: MaybePromise<Date>; updatedAt: MaybePromise<Date>; name: MaybePromise<string>; viewCount: MaybePromise<number>; }'.
                Type 'null' is not assignable to type 'Blog | { id: MaybePromise<number>; createdAt: MaybePromise<Date>; updatedAt: MaybePromise<Date>; name: MaybePromise<string>; viewCount: MaybePromise<number>; }'.

At first I thought the possible null return type modelling the fact that the record may not exist in the database. But actually it seems that photon will throw in that case:
Using ts-node version 8.4.1, typescript version 3.7.2
🚀 Server ready at http://localhost:4000
Error: 
Invalid `photon.()` invocation in /Users/jasonkuhrt/projects/prisma-labs/nexus-prisma/examples/blog/src/schema/Query.ts:22:12



Reason: Error occurred during query execution:
ConnectorError(RecordDoesNotExist)

    at PhotonFetcher.<anonymous> (/Users/jasonkuhrt/projects/prisma-labs/nexus-prisma/examples/blog/node_modules/@generated/photon/index.js:51:27)
    at Generator.throw (<anonymous>)
    at rejected (/Users/jasonkuhrt/projects/prisma-labs/nexus-prisma/examples/blog/node_modules/@generated/photon/index.js:6:65)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

Therefore I'm not sure what the null is doing? Working around the types is easy enough:
    t.field('blog', {
      type: 'Blog',
      args: { id: intArg({ required: true }) },
      resolve(_root, args, ctx) {
        return ctx.photon.blogs
          .findOne({ where: { id: args.id } })
          .then(maybeBlog => {
            if (!maybeBlog) {
              throw new Error(`No such user: ${args.id}`)
            }
            return maybeBlog
          })
      },
    })
But is silly, if that code is actually never going to be called.

Closing comment (2019-11-07T20:28:07Z): Yes, throwing an error seems like a bug in this case. Closing as a duplicate of #288 for now. In case you'd like to change this behavior, please reopen or open a new issue 🙏