-
-
Notifications
You must be signed in to change notification settings - Fork 128
Description
Description and expected behavior
I am currently using the zenstack Restful API Handler with calling the following endpoint:
http://localhost:4001/api/user?include=offices
Below are my models (I have removed some fields to not overcomplicate things):
model User extends Base {
externalId String
firstName String @length(1, 256)
lastName String @length(1, 256)
email String
username String
offices UserOffice[]
}
model UserOffice extends NoIdBase {
user User @relation(fields: [userId], references: [id], onDelete: Restrict)
userId String @db.Uuid
office Office @relation(fields: [officeId], references: [id], onDelete: Restrict)
officeId String @db.Uuid
@@unique([userId, officeId])
}
model Office extends Base {
name String
users UserOffice[]
country String @default('Australia')
state String @default('Victoria')
}
What I have received is as follow (I have removed some fields to not overcomplicate things):
{
"jsonapi": {
"version": "1.1"
},
"links": {
"self": "http://localhost:4001/api/user",
"first": "http://localhost:4001/api/user?filter%5Bid%5D=ae3ae174-d4fe-4869-8218-6a020d6878c5%2C68fb45cf-abac-4894-b6e0-2342911333fc%2C75908cc4-be29-4e1a-868a-3c12efec78be%2Cef95f21b-3e92-4044-a988-65dbd0a88b1b&page%5Blimit%5D=100",
"last": "http://localhost:4001/api/user?filter%5Bid%5D=ae3ae174-d4fe-4869-8218-6a020d6878c5%2C68fb45cf-abac-4894-b6e0-2342911333fc%2C75908cc4-be29-4e1a-868a-3c12efec78be%2Cef95f21b-3e92-4044-a988-65dbd0a88b1b&page%5Boffset%5D=0",
"prev": null,
"next": null
},
"data": [
{
"type": "user",
"id": "68fb45cf-abac-4894-b6e0-2342911333fc",
"attributes": {
"clientId": "9435cf4c-734c-4ae4-9636-6180b9b1bb41",
"createdAt": "2025-09-23T03:18:36.229Z",
"createdBy": "ae3ae174-d4fe-4869-8218-6a020d6878c5",
"updatedAt": "2025-09-30T01:26:58.867Z",
"updatedBy": "ae3ae174-d4fe-4869-8218-6a020d6878c5",
"firstName": "Lauren",
"lastName": "Admin1",
"email": "dev+test+fundraiser1@test.com.au",
"username": "dev+test+fundraiser1@test.com.au",
"mobile": "0434511817",
"status": "Active",
},
"links": {
"self": "http://localhost:4001/api/user/68fb45cf-abac-4894-b6e0-2342911333fc"
},
"relationships": {
"offices": {
"links": {
"self": "http://localhost:4001/api/user/68fb45cf-abac-4894-b6e0-2342911333fc/relationships/offices",
"related": "http://localhost:4001/api/user/68fb45cf-abac-4894-b6e0-2342911333fc/offices"
},
"data": [
{
"type": "userOffice",
"id": "68fb45cf-abac-4894-b6e0-2342911333fc_e282dcd6-ee66-4fe2-8e73-718b2c1b6866"
}
]
},
}
},
{
"type": "user",
"id": "75908cc4-be29-4e1a-868a-3c12efec78be",
"attributes": {
"clientId": "9435cf4c-734c-4ae4-9636-6180b9b1bb41",
"createdAt": "2025-09-30T06:15:25.248Z",
"createdBy": "ae3ae174-d4fe-4869-8218-6a020d6878c5",
"updatedAt": "2025-09-30T06:15:25.248Z",
"updatedBy": null,
"externalId": "993e7488-d061-703b-4102-a9d07a8e1680",
"firstName": "Steven",
"lastName": "4",
"email": "steven+fund4@test.com.au",
"username": "steven+fund4@test.com.au",
"mobile": "0434511817",
"status": "Inactive",
},
"links": {
"self": "http://localhost:4001/api/user/75908cc4-be29-4e1a-868a-3c12efec78be"
},
"relationships": {
"offices": {
"links": {
"self": "http://localhost:4001/api/user/75908cc4-be29-4e1a-868a-3c12efec78be/relationships/offices",
"related": "http://localhost:4001/api/user/75908cc4-be29-4e1a-868a-3c12efec78be/offices"
},
"data": [
{
"type": "userOffice",
"id": "75908cc4-be29-4e1a-868a-3c12efec78be_94f745fe-e145-49cc-a556-8a578c21962f"
},
{
"type": "userOffice",
"id": "75908cc4-be29-4e1a-868a-3c12efec78be_e282dcd6-ee66-4fe2-8e73-718b2c1b6866"
}
]
},
}
},
{
"type": "user",
"id": "ef95f21b-3e92-4044-a988-65dbd0a88b1b",
"attributes": {
"clientId": "9435cf4c-734c-4ae4-9636-6180b9b1bb41",
"createdAt": "2025-09-24T05:41:14.067Z",
"createdBy": "ae3ae174-d4fe-4869-8218-6a020d6878c5",
"updatedAt": "2025-10-01T05:44:32.206Z",
"updatedBy": "ae3ae174-d4fe-4869-8218-6a020d6878c5",
"firstName": "Steven123",
"lastName": "Admin1",
"email": "steven+fund10@ test.com.au",
"username": "steven+fund10@test.com.au",
"mobile": "0434511817",
"status": "Active",
},
"links": {
"self": "http://localhost:4001/api/user/ef95f21b-3e92-4044-a988-65dbd0a88b1b"
},
"relationships": {
"offices": {
"links": {
"self": "http://localhost:4001/api/user/ef95f21b-3e92-4044-a988-65dbd0a88b1b/relationships/offices",
"related": "http://localhost:4001/api/user/ef95f21b-3e92-4044-a988-65dbd0a88b1b/offices"
},
"data": [
{
"type": "userOffice",
"id": "ef95f21b-3e92-4044-a988-65dbd0a88b1b_e282dcd6-ee66-4fe2-8e73-718b2c1b6866"
},
{
"type": "userOffice",
"id": "ef95f21b-3e92-4044-a988-65dbd0a88b1b_94f745fe-e145-49cc-a556-8a578c21962f"
}
]
},
}
}
],
"included": [
{
"type": "userOffice",
"id": "68fb45cf-abac-4894-b6e0-2342911333fc_e282dcd6-ee66-4fe2-8e73-718b2c1b6866",
"attributes": {
"clientId": "9435cf4c-734c-4ae4-9636-6180b9b1bb41",
"createdAt": "2025-09-23T03:18:36.233Z",
"createdBy": "ae3ae174-d4fe-4869-8218-6a020d6878c5",
"updatedAt": "2025-09-23T03:18:36.233Z",
"updatedBy": null,
"userId": "68fb45cf-abac-4894-b6e0-2342911333fc",
"officeId": "e282dcd6-ee66-4fe2-8e73-718b2c1b6866",
"isHomeOffice": true
},
"links": {
"self": "http://localhost:4001/api/userOffice/68fb45cf-abac-4894-b6e0-2342911333fc_e282dcd6-ee66-4fe2-8e73-718b2c1b6866"
},
"relationships": {
"user": {
"links": {
"self": "http://localhost:4001/api/userOffice/68fb45cf-abac-4894-b6e0-2342911333fc_e282dcd6-ee66-4fe2-8e73-718b2c1b6866/relationships/user",
"related": "http://localhost:4001/api/userOffice/68fb45cf-abac-4894-b6e0-2342911333fc_e282dcd6-ee66-4fe2-8e73-718b2c1b6866/user"
}
},
"office": {
"links": {
"self": "http://localhost:4001/api/userOffice/68fb45cf-abac-4894-b6e0-2342911333fc_e282dcd6-ee66-4fe2-8e73-718b2c1b6866/relationships/office",
"related": "http://localhost:4001/api/userOffice/68fb45cf-abac-4894-b6e0-2342911333fc_e282dcd6-ee66-4fe2-8e73-718b2c1b6866/office"
}
}
}
}
],
"meta": {
"serialization": {
"values": {
"data.0.attributes.createdAt": [
"Date"
],
"data.0.attributes.updatedAt": [
"Date"
],
"data.1.attributes.createdAt": [
"Date"
],
"data.1.attributes.updatedAt": [
"Date"
],
"data.2.attributes.createdAt": [
"Date"
],
"data.2.attributes.updatedAt": [
"Date"
],
"data.3.attributes.createdAt": [
"Date"
],
"data.3.attributes.updatedAt": [
"Date"
],
"included.0.attributes.createdAt": [
"Date"
],
"included.0.attributes.updatedAt": [
"Date"
]
}
},
"total": 3
}
}
As you can see I want to include the many-to-many relations (in our case offices/userOffice). The data we have received back shows all the relationships (with just the Ids). However, the included part is only returning 1 single userOffice even though there should be multiple (2 offices in our case).
When I include One-to-Many relationships, for example one user have one level, (or one level have many user) it would then show the multiple level based on the users returned, which is good.
The problem here is that when it is many-to-many relationship, it is not returning all the relations. Rather, it only return one (from what I can see, which is the first user's userOffice).
Please any assistant would be great, otherwise, it would be painful to keep calling multiple endpoints to list down all the relationships.
Environment:
- ZenStack version: 2.19.1
- Prisma version: 6.16.2
- Database type: Postgresql