ardatan / ardatan/graphql-tools
batchDelegateToSchema creates a duplicate of data from response for every resulting fields
- Dominant language
- TypeScript
- Stars
- 5.4k
- Forks
- 830
- Avg merge
- 10h 59m
- Merged PRs (30d)
- 45
Description
Hello,
I've been implementing in an API the method `batchDelegateToSchema` from the library.
I'm sharing the following media to show the issue I have with the response and details immediately below

As you see from that query I'm calling I'm receiving a result and what is wrong I'm getting the data duplicated for the fields which should be empty objects.
In my example, I'm retrieving data for one candidate and I want to know the events that the candidate has signed.
As per DB the candidate has only APPOINTMENT_PHONE as event so I'm expecting this resulting object from the query
```Json
{
"data": {
"candidate": {
"id": "CY-001745",
"callReminders": {
"nodes": [
{
"id": "33116",
"startTime": "2023-01-10T08:57:00.000Z",
"type": "APPOINTMENT_PHONE"
}
],
"totalCount": 1
},
"siteAppointments": {
"nodes": [
],
"totalCount": 0
}
}
}
}
```
Instead, I see the same result replicated in the `siteAppointments` which is wrong.
As ref of wrong response
```json
{
"data": {
"candidate": {
"id": "CY-001745",
"callReminders": {
"nodes": [
{
"id": "33116",
"startTime": "2023-01-10T08:57:00.000Z",
"type": "APPOINTMENT_PHONE"
}
],
"totalCount": 1
},
"siteAppointments": { -- THIS HEAR HAS TO BE EMPTY [] --
"nodes": [
{
"id": "33116",
"startTime": "2023-01-10T08:57:00.000Z",
"type": "APPOINTMENT_PHONE"
}
],
"totalCount": 1
}
}
}
}
```
I spent already hours understanding the issue and I'm sharing what I debugged
This is the resolver
```javascript
events: {
selectionSet: '{ id }',
resolve(candidate, args, context, info) {
return batchDelegateToSchema({
schema: event,
operation: 'query',
fieldName: 'eventsByOwner',
key: candidate.id,
transforms: [transformEventsByOwner],
argsFromKeys: keys => ({
...args,
filter: {
...(args?.filter ?? {}),
ownerTypes: ['CANDIDATE'],
ownerIds: keys,
},
}),
valuesFromResults: (results, keys) => {
const allEvents = keys
.map(findByOwnerId(results))
.map(mapToConnection);
console.log('allEvents: ', JSON.stringify(allEvents, null, 2));
return allEvents;
},
context,
info,
});
},
},
```
On the `console.log('allEvents: ', JSON.stringify(allEvents, null, 2));`I see the result I need the correct one
```json
allEvents: [
{
"totalCount": 1,
"nodes": [
{
"id": "33116",
"startTime": "2023-01-10T08:57:00.000Z",
"type": "APPOINTMENT_PHONE",
"__typename": "Event"
}
]
}
]
```
But for some reason after that the result is duplicated inside the other field `siteAppointments`
I have no clue what's wrong here and I would like to find out a solution to that as it is blocking my release :(
As a detail the other methods used here
```javascript
/**
* Find an item in list of results by owner id.
*
* @param {Object[]} results - List of results.
* @param {string} results[].ownerId - The item's owner id.
* @returns {Object|undefined} - The item with matching owner id or undefined when item not found.
*/
export function findByOwnerId(results) {
return id => results?.find(item => item?.ownerId === id);
}
/**
* Map a result to a generic connection interface.
*
* @param {Object} result - A result (potentially empty or undefined).
* @param {?number} result.totalCount - Total count of entities.
* @param {?Object[]} result.nodes - Array of items.
* @returns {{totalCount: number, nodes: Object[]}} - A connection with nodes and totalCount.
*/
export function mapToConnection(result) {
return {
totalCount: result?.totalCount ?? 0,
nodes: result?.nodes ?? [],
};
}
export const transformEventsByOwner = new WrapQuery(
['eventsByOwner'],
extendedSelection('ownerId'),
identity,
);
```
I hope you can help me with this issue
Thanks :)
Contributor guide
Research direction
Start at the batchDelegateToSchema entry point and compare its per-key result mapping with the resolver's valuesFromResults callback, including findByOwnerId and mapToConnection. Reproduce the candidate query and verify that an unmatched siteAppointments result stays as nodes: [] with totalCount: 0 rather than copying callReminders data.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, javascript, typescript
- Domain
- api, backend, backend-api-design
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100