Skip to content

Commit ab9d27f

Browse files
authored
fix(delegate): avoid merging into object of Decimal, Date, etc. (#1489)
1 parent 4c74169 commit ab9d27f

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed

packages/runtime/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"decimal.js": "^10.4.2",
8484
"deepcopy": "^2.1.0",
8585
"deepmerge": "^4.3.1",
86+
"is-plain-object": "^5.0.0",
8687
"logic-solver": "^2.0.1",
8788
"lower-case-first": "^2.0.2",
8889
"pluralize": "^8.0.0",

packages/runtime/src/enhancements/delegate.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
import deepcopy from 'deepcopy';
33
import deepmerge, { type ArrayMergeOptions } from 'deepmerge';
4+
import { isPlainObject } from 'is-plain-object';
45
import { lowerCaseFirst } from 'lower-case-first';
56
import { DELEGATE_AUX_RELATION_PREFIX } from '../constants';
67
import {
@@ -1094,6 +1095,7 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
10941095

10951096
const result = deepmerge(upMerged, downMerged, {
10961097
arrayMerge: combineMerge,
1098+
isMergeableObject: (v) => isPlainObject(v) || Array.isArray(v), // avoid messing with Decimal, Date, etc.
10971099
});
10981100
return result;
10991101
}

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { createPostgresDb, dropPostgresDb, loadSchema } from '@zenstackhq/testtools';
2+
import Decimal from 'decimal.js';
3+
4+
describe('issue 1487', () => {
5+
it('regression2', async () => {
6+
const dbUrl = await createPostgresDb('issue-1487');
7+
let prisma: any;
8+
9+
try {
10+
const r = await loadSchema(
11+
`
12+
model LineItem {
13+
id Int @id @default(autoincrement())
14+
price Decimal
15+
createdAt DateTime @default(now())
16+
17+
orderId Int
18+
order Order @relation(fields: [orderId], references: [id])
19+
}
20+
model Order extends BaseType {
21+
total Decimal
22+
createdAt DateTime @default(now())
23+
lineItems LineItem[]
24+
}
25+
model BaseType {
26+
id Int @id @default(autoincrement())
27+
entityType String
28+
29+
@@delegate(entityType)
30+
}
31+
`,
32+
{
33+
provider: 'postgresql',
34+
dbUrl,
35+
enhancements: ['omit', 'delegate'],
36+
}
37+
);
38+
39+
prisma = r.prisma;
40+
const db = r.enhance();
41+
42+
const create = await db.Order.create({
43+
data: {
44+
total: new Decimal(100_100.99),
45+
lineItems: { create: [{ price: 90_000.66 }, { price: 20_100.33 }] },
46+
},
47+
});
48+
49+
const order = await db.Order.findFirst({ where: { id: create.id }, include: { lineItems: true } });
50+
expect(Decimal.isDecimal(order.total)).toBe(true);
51+
expect(order.createdAt instanceof Date).toBe(true);
52+
expect(order.total.toString()).toEqual('100100.99');
53+
order.lineItems.forEach((item: any) => {
54+
expect(Decimal.isDecimal(item.price)).toBe(true);
55+
expect(item.price.toString()).not.toEqual('[object Object]');
56+
});
57+
58+
const lineItems = await db.LineItem.findMany();
59+
lineItems.forEach((item: any) => {
60+
expect(item.createdAt instanceof Date).toBe(true);
61+
expect(Decimal.isDecimal(item.price)).toBe(true);
62+
expect(item.price.toString()).not.toEqual('[object Object]');
63+
});
64+
} finally {
65+
if (prisma) {
66+
await prisma.$disconnect();
67+
}
68+
await dropPostgresDb('issue-1487');
69+
}
70+
});
71+
});

0 commit comments

Comments
 (0)