Skip to content

Commit 4fc4cf7

Browse files
authored
fix(server): rest handler not returning correct id when model with compound id is read as a relation (#1784)
1 parent c0ab830 commit 4fc4cf7

File tree

2 files changed

+62
-16
lines changed

2 files changed

+62
-16
lines changed

Diff for: packages/server/src/api/rest/index.ts

+28-16
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
DbClientContract,
66
FieldInfo,
77
PrismaErrorCode,
8+
clone,
89
enumerate,
910
getIdFields,
1011
isPrismaClientKnownRequestError,
@@ -1120,22 +1121,8 @@ class RequestHandler extends APIHandlerBase {
11201121
throw new Error(`serializer not found for model ${model}`);
11211122
}
11221123

1123-
const typeInfo = this.typeMap[model];
1124-
1125-
let itemsWithId: any = items;
1126-
if (typeInfo.idFields.length > 1 && Array.isArray(items)) {
1127-
itemsWithId = items.map((item: any) => {
1128-
return {
1129-
...item,
1130-
[this.makeIdKey(typeInfo.idFields)]: this.makeCompoundId(typeInfo.idFields, item),
1131-
};
1132-
});
1133-
} else if (typeInfo.idFields.length > 1 && typeof items === 'object') {
1134-
itemsWithId = {
1135-
...items,
1136-
[this.makeIdKey(typeInfo.idFields)]: this.makeCompoundId(typeInfo.idFields, items),
1137-
};
1138-
}
1124+
const itemsWithId = clone(items);
1125+
this.injectCompoundId(model, itemsWithId);
11391126

11401127
// serialize to JSON:API structure
11411128
const serialized = await serializer.serialize(itemsWithId, options);
@@ -1154,6 +1141,31 @@ class RequestHandler extends APIHandlerBase {
11541141
return result;
11551142
}
11561143

1144+
private injectCompoundId(model: string, items: unknown) {
1145+
const typeInfo = this.typeMap[lowerCaseFirst(model)];
1146+
if (!typeInfo) {
1147+
return;
1148+
}
1149+
1150+
// recursively traverse the entity to create synthetic ID field for models with compound ID
1151+
enumerate(items).forEach((item: any) => {
1152+
if (!item) {
1153+
return;
1154+
}
1155+
1156+
if (typeInfo.idFields.length > 1) {
1157+
item[this.makeIdKey(typeInfo.idFields)] = this.makeCompoundId(typeInfo.idFields, item);
1158+
}
1159+
1160+
for (const [key, value] of Object.entries(item)) {
1161+
if (typeInfo.relationships[key]) {
1162+
// field is a relationship, recurse
1163+
this.injectCompoundId(typeInfo.relationships[key].type, value);
1164+
}
1165+
}
1166+
});
1167+
}
1168+
11571169
private toPlainObject(data: any): any {
11581170
if (data === undefined || data === null) {
11591171
return data;

Diff for: packages/server/tests/api/rest.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,40 @@ describe('REST server tests', () => {
13731373
},
13741374
});
13751375
});
1376+
1377+
it('get as relationship', async () => {
1378+
const r = await handler({
1379+
method: 'get',
1380+
path: `/post/1`,
1381+
query: { include: 'likes' },
1382+
prisma,
1383+
});
1384+
1385+
expect(r.status).toBe(200);
1386+
expect(r.body).toMatchObject({
1387+
data: {
1388+
relationships: {
1389+
likes: {
1390+
data: [{ type: 'postLike', id: `1${idDivider}user2` }],
1391+
},
1392+
},
1393+
},
1394+
included: [
1395+
expect.objectContaining({
1396+
type: 'postLike',
1397+
id: '1_user2',
1398+
attributes: {
1399+
postId: 1,
1400+
userId: 'user2',
1401+
superLike: false,
1402+
},
1403+
links: {
1404+
self: 'http://localhost/api/postLike/1_user2',
1405+
},
1406+
}),
1407+
],
1408+
});
1409+
});
13761410
});
13771411
});
13781412

0 commit comments

Comments
 (0)