Search code examples
nuxt.jsprisma

Nuxt: how to customize prisma error and use this customization with useFetch?


My purpose is to create a person in the mysql database using prisma in the backend and nuxt useFetch in the frontend.

At the moment the frontend is as follows

type Schema = z.output<typeof schema>;
type person = {
  firstName: string;
  lastName: string;
  email: string;
  phone: string;
  memberSince: string;
  memberLastYear: string;
};
const state: person = reactive({
  firstName: "",
  lastName: "",
  email: "",
  phone: "",
  memberSince: "",
  memberLastYear: "",
});

async function onSubmit(event: FormSubmitEvent<any>) {
  console.log("submit");

  const { data, pending, error } = await useFetch("api/person", {
    method: "POST",
    body: event.data,
  });

  if (data) {
    console.log("logging data");
    console.log(toRaw(data.value));
    personsStore.addPerson(toRaw(data.value));
  }
  if (error) {
    console.log("logging error");
    console.log(error.value);
  }

  emit("close");
}

The code is in a front end modal that includes the form hence the onSubmit function with the final emit('close') statement.

In the prima schema there is a unique constraint to prevent the user to create 2 persons with the same firstName and lastName.

model Person {

  id      Int      @id @default(autoincrement())
  firstName String @db.VarChar(70)
  lastName String @db.VarChar(70)
  email   String   @db.VarChar(255)
  phone String @db.VarChar (20)
  memberSince DateTime  @db.Date
  memberLastYear String @db.VarChar(10)

  @@unique([firstName,lastName], name:"fullName")

}

At the moment the code in my end point is this

import { PrismaClient, Prisma } from "@prisma/client";
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
  const body = await readBody(event);

  console.log("in backend create person");
 
  let memberSince = new Date(body.memberSince);
 try{
      const person = await prisma.person.create({
      data: {
        firstName: body.firstName,
        lastName: body.lastName,
        email: body.email,
        phone: body.phone,
        memberSince: memberSince,
        memberLastYear: body.memberLastYear,
      },
    });
     return person
 } catch(e){
   throw new Error('something went wrong when creating the person in the database')
 }
});

I intend to work on the catch part in order to throw a custom message when the user attempts to create a duplicate pair (firstName lastName) I tried many things never succeeding . I need some help to write the catch clause here but also on how to retrieve this message in the front end.

At the moment I cannot even get my custom message i.e. "something went wrong when creating the person in the database" but only the original error message which is "Error: [POST] "api/person": 500 Internal Server Error"

Thanks in advance.


Solution

  • After fighting for a while I found this solution (may be not the best or the most orthodox but it works)

    import { PrismaClient, Prisma } from "@prisma/client";
    const prisma = new PrismaClient();
    export default defineEventHandler(async (event) => {
      const body = await readBody(event);
    
      console.log("in backend create person");
    
      let memberSince = new Date(body.memberSince);
      let person = null;
     
      await prisma.person
        .create({
          data: {
            firstName: body.firstName,
            lastName: body.lastName,
            email: body.email,
            phone: body.phone,
            memberSince: memberSince,
            memberLastYear: body.memberLastYear,
          },
        })
        .then((response) => {
          person = response;
        })
        .catch((error) => {
          if (error instanceof Prisma.PrismaClientKnownRequestError) {
            // The .code property can be accessed in a type-safe manner
            if (error.code === "P2002") {
              error = createError({
                statusCode: 500,
                statusMessage: "Duplicate fullName not accepted",
              }); 
            }
          }
          throw error;
        });
      return person;
    });