Soft Deleting with $extends from Prisma

If you've attempted to use prisma.$use, you may have encountered a "deprecated" message. Your initial reaction might be to consult the documentation for an alternative. However, you won't find one there. If you're interested in soft deleting a record from a table, you probably want to use $extends as of prisma version 4.16.0+.

First, make sure you've added a field named deletedAt. This can be set as either a boolean or a Date as recommended by Prisma.

For the sake of illustration, let's add it to our Post model.

model Post {
    id      Int @id @default(autoincrement())
    title   String
    content String

    deletedAt DateTime?
}

Now we can use our $extend helper from prisma

const db = prisma.$extends({
  model: {
    post: {
      async delete({ where }: { id: string }) {
        return prisma.post.update({
          where: {
            ...where,
          },
          data: {
            deletedAt: new Date(),
          },
        });
      },
    },
  },
});

Here, we're targeting our Post model and modifying the delete function to act as an update. In doing so, we are updating our deletedAt record to set a date.

We want to omit deleted records when querying our posts. To achieve this, we can target the operations to access specific actions like findMany, findUnique, or findFirst.

  query: {
    post: {
      async $allOperations({ operation, args, query }) {
        if (
          operation === "findMany" ||
          operation === "findUnique" ||
          operation === "findFirst"
        ) {
          args.where = { ...args.where, deletedAt: null };
        }

        return query(args);
      },
    },
  },

Depending on your application, you may not need all find operations.

Querying your data in this way ensures that records marked as deletedAt will not be displayed.

Full Code

const db = prisma.$extends({
    model: {
        post: {
            async delete({ where }: { id: string; }) {
                return prisma.post.update({
                    where: {
                        ...where,
                    },
                    data: {
                        deletedAt: new Date(),
                    },
                 });
            }
        }
    }
}),
  query: {
    post: {
      async $allOperations({ operation, args, query }) {
        if (
          operation === "findMany" ||
          operation === "findUnique" ||
          operation === "findFirst"
        ) {
          args.where = { ...args.where, deletedAt: null };
        }

        return query(args);
      },
    },
  },

References

https://www.prisma.io/docs/orm/reference/prisma-client-reference#extends https://www.prisma.io/docs/orm/prisma-client/client-extensions