Skip to content

Commit 04ddd6c

Browse files
ivatraIvatraolivierwilkinson
authored
fix: including models in delete queries (#19)
The delete middleware does not spread args when handling a top level delete, this means that includes (and selects etc) are not found in the final params for the query. Spread args in the top level case for delete. --------- Co-authored-by: Ivatra <[email protected]> Co-authored-by: Olivier Wilkinson <[email protected]>
1 parent d1f62bc commit 04ddd6c

File tree

4 files changed

+94
-6
lines changed

4 files changed

+94
-6
lines changed

src/lib/actionMiddleware.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,24 @@ function createDeleteParams(
5959
};
6060
}
6161

62+
if (!!params.scope) {
63+
return {
64+
...params,
65+
action: "update",
66+
args: {
67+
where: params.args,
68+
data: {
69+
[field]: createValue(true),
70+
},
71+
},
72+
};
73+
}
74+
6275
return {
6376
...params,
6477
action: "update",
6578
args: {
66-
where: params.args?.where || params.args,
79+
...params.args,
6780
data: {
6881
[field]: createValue(true),
6982
},

test/unit/include.test.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { set } from "lodash";
22
import faker from "faker";
33

44
import { createSoftDeleteMiddleware } from "../../src";
5-
import { createParams } from "./utils/createParams";
5+
import { createParams, ActionByModel } from "./utils/createParams";
66

77
describe("include", () => {
88
it("does not change include params if model is not in the list", async () => {
@@ -21,6 +21,44 @@ describe("include", () => {
2121
expect(next).toHaveBeenCalledWith(params);
2222
});
2323

24+
it.each([
25+
"delete",
26+
"update",
27+
"upsert",
28+
"findFirst",
29+
"findFirstOrThrow",
30+
"findUnique",
31+
"findUniqueOrThrow",
32+
"findMany",
33+
] as Array<ActionByModel<"User">>)(
34+
"can include records for configured models in %s",
35+
async (action) => {
36+
const middleware = createSoftDeleteMiddleware({
37+
models: { User: true },
38+
});
39+
40+
const params = createParams("User", action, {
41+
where: { id: 1 },
42+
include: {
43+
comments: true,
44+
},
45+
});
46+
47+
const next = jest.fn(() =>
48+
Promise.resolve({
49+
comments: [{ deleted: true }, { deleted: false }],
50+
})
51+
);
52+
53+
await middleware(params, next);
54+
55+
// @ts-expect-error - ts doesn't know there has been a call
56+
expect(next.mock.calls[0][0]?.args?.include).toEqual({
57+
comments: true,
58+
});
59+
}
60+
);
61+
2462
it("uses params to exclude deleted records from toMany includes", async () => {
2563
const middleware = createSoftDeleteMiddleware({
2664
models: { Comment: true },
@@ -138,7 +176,7 @@ describe("include", () => {
138176
expect(next).toHaveBeenCalledWith(params);
139177
expect(result).toEqual({ author: null });
140178
});
141-
179+
142180
it("does not manually exclude non-deleted records from toOne include with nested includes", async () => {
143181
const middleware = createSoftDeleteMiddleware({
144182
models: { User: true },
@@ -213,7 +251,6 @@ describe("include", () => {
213251
});
214252
});
215253

216-
217254
it("allows explicitly including deleted records using include", async () => {
218255
const middleware = createSoftDeleteMiddleware({
219256
models: { Comment: true },

test/unit/select.test.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { set } from "lodash";
22
import faker from "faker";
33

44
import { createSoftDeleteMiddleware } from "../../src";
5-
import { createParams } from "./utils/createParams";
5+
import { ActionByModel, createParams } from "./utils/createParams";
66

77
describe("select", () => {
88
it("does not change select params if model is not in the list", async () => {
@@ -21,6 +21,44 @@ describe("select", () => {
2121
expect(next).toHaveBeenCalledWith(params);
2222
});
2323

24+
it.each([
25+
"delete",
26+
"update",
27+
"upsert",
28+
"findFirst",
29+
"findFirstOrThrow",
30+
"findUnique",
31+
"findUniqueOrThrow",
32+
"findMany",
33+
] as Array<ActionByModel<"User">>)(
34+
"can select records for configured models in %s",
35+
async (action) => {
36+
const middleware = createSoftDeleteMiddleware({
37+
models: { User: true },
38+
});
39+
40+
const params = createParams("User", action, {
41+
where: { id: 1 },
42+
select: {
43+
comments: true,
44+
},
45+
});
46+
47+
const next = jest.fn(() =>
48+
Promise.resolve({
49+
comments: [{ deleted: true }, { deleted: false }],
50+
})
51+
);
52+
53+
await middleware(params, next);
54+
55+
// @ts-expect-error - ts doesn't know there has been a call
56+
expect(next.mock.calls[0][0]?.args?.select).toEqual({
57+
comments: true,
58+
});
59+
}
60+
);
61+
2462
it("excludes deleted records from selects", async () => {
2563
const middleware = createSoftDeleteMiddleware({
2664
models: { Comment: true },

test/unit/utils/createParams.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type IncludeByModel<Model extends Prisma.ModelName> = Model extends "User"
3030
? Prisma.CommentInclude
3131
: never;
3232

33-
type ActionByModel<Model extends Prisma.ModelName> =
33+
export type ActionByModel<Model extends Prisma.ModelName> =
3434
| keyof DelegateByModel<Model>
3535
| "connectOrCreate"
3636
| "select"

0 commit comments

Comments
 (0)