I am using olivierwilkinson/prisma-soft-delete-middleware to keep important models in the DB even after they are deleted. However, when used in conjunction with Nexus the middleware is ignored, which leads to runtime errors due to inconsistencies withe the gql schema.
Repro Steps/Link
db.ts:
export const db = new PrismaClient()
db.$use(
createSoftDeleteMiddleware({
models: {
Category: true,
},
defaultConfig: {
field: 'deletedAt',
createValue: (deleted) => {
if (deleted) return new Date()
return null
},
},
}),
)
schema.prisma:
model Post {
categoryId String?
category Category? @relation
}
model Category {
deletedAt DateTime?
createdBy User
name String
}
Post.ts:
import {
Post as PrismaPost,
} from 'nexus-prisma'
const Post = objectType({
name: PrismaPost.$name,
definition(t) {
t.field(PrismaPost.category)
},
})
Category.ts:
import {
Category as Prisma Category,
} from 'nexus-prisma'
const Category = objectType({
name: PrismaCategory.$name,
definition(t) {
t.field(PrismaCategory.createdBy)
},
})
When querying a Post with a soft-deleted category, the category will be returned. This in itself would not cause issues other than the data being accessible when it shouldn't.
query post {
post(id: 1) {
category {
name
}
}
}
However, errors can arise when querying non-scalar fields:
query post {
post(id: 1) {
category {
name
createdBy {
firstname
}
}
}
}
For some reason the nested access to the Category.createdBy field will return null because of the Category soft delete, but the category itself will not be null. In this specific case, this triggers a GraphQL error because my schema sets the createdBy as a non-null field on the Category type.
I'm not sure what's causing this partial support, but it's giving me headaches.
Current workaround is to implement a custom resolver in the object type declaration that defines a field that points to a soft-deletable record.
For example:
const Post = objectType({
name: PrismaPost.$name,
definition(t) {
t.field(PrismaPost.category.name, {
...PrismaPost.category,
resolve(root, args, ctx) {
if (!root.categoryId) return null
// Explicit use of `findUnique` will get handled by the middleware.
return ctx.db.category.findUnique({ where: { id: root.categoryId } })
},
})
},
})
Description
I am using olivierwilkinson/prisma-soft-delete-middleware to keep important models in the DB even after they are deleted. However, when used in conjunction with Nexus the middleware is ignored, which leads to runtime errors due to inconsistencies withe the gql schema.
Repro Steps/Link
db.ts
:schema.prisma
:Post.ts
:Category.ts
:When querying a
Post
with a soft-deletedcategory
, the category will be returned. This in itself would not cause issues other than the data being accessible when it shouldn't.However, errors can arise when querying non-scalar fields:
For some reason the nested access to the
Category.createdBy
field will returnnull
because of theCategory
soft delete, but the category itself will not be null. In this specific case, this triggers a GraphQL error because my schema sets thecreatedBy
as a non-null field on theCategory
type.I'm not sure what's causing this partial support, but it's giving me headaches.
Current workaround is to implement a custom resolver in the object type declaration that defines a field that points to a soft-deletable record.
For example:
Any insights would be appreciated here!