Skip to content

Commit 64ae496

Browse files
committed
attempt fix
1 parent 4207f94 commit 64ae496

File tree

1 file changed

+41
-7
lines changed

1 file changed

+41
-7
lines changed

packages/delegate/src/defaultMergedResolver.ts

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,14 @@ export function defaultMergedResolver(
9494
if (
9595
fieldNodesByType?.every((fieldNode) => {
9696
const responseKey = fieldNode.alias?.value ?? fieldNode.name.value;
97-
if (Object.prototype.hasOwnProperty.call(parent, responseKey)) {
98-
return true;
99-
}
100-
return false;
97+
return Object.prototype.hasOwnProperty.call(parent, responseKey);
10198
})
10299
) {
103100
handleResult(parent, responseKey, context, info);
101+
} else {
102+
// not all fields are present, we need to resolve more leftovers
103+
// this can occur when there are circular @requires, see requires-circular audit test
104+
handleLeftOver(parent, context, info, leftOver);
104105
}
105106
return deferred.promise;
106107
}
@@ -388,15 +389,48 @@ function handleDeferredResolverResult<TContext extends Record<string, any>>(
388389
const deferredFields =
389390
leftOver.missingFieldsParentDeferredMap.get(leftOverParent);
390391
if (deferredFields) {
392+
const stitchingInfo = info.schema.extensions?.[
393+
'stitchingInfo'
394+
] as StitchingInfo;
395+
const parentTypeName = leftOverParent?.__typename || info.parentType.name;
396+
const resolvedKeys = new Set<string>();
391397
for (const [responseKey, deferred] of deferredFields) {
392-
// If the deferred field is resolved, resolve the deferred field
393-
if (Object.prototype.hasOwnProperty.call(resolverResult, responseKey)) {
398+
// after handleResolverResult, check if the field is now in the parent
399+
if (Object.prototype.hasOwnProperty.call(leftOverParent, responseKey)) {
400+
// field was added to parent by handleResolverResult
394401
deferred.resolve(
395402
handleResult(leftOverParent, responseKey, context, info),
396403
);
404+
resolvedKeys.add(responseKey);
405+
} else {
406+
// check if the required fields for this deferred field are now satisfied
407+
const fieldNodesByType =
408+
stitchingInfo?.fieldNodesByField?.[parentTypeName]?.[responseKey];
409+
if (fieldNodesByType) {
410+
if (
411+
fieldNodesByType.every((fieldNode) => {
412+
const requiredKey =
413+
fieldNode.alias?.value ?? fieldNode.name.value;
414+
return Object.prototype.hasOwnProperty.call(
415+
leftOverParent,
416+
requiredKey,
417+
);
418+
})
419+
) {
420+
// requirements are satisfied, trigger handleLeftOver to fetch this field
421+
handleLeftOver(leftOverParent, context, info, leftOver);
422+
}
423+
}
397424
}
398425
}
399-
leftOver.missingFieldsParentDeferredMap.delete(leftOverParent);
426+
// delete resolved deferred fields
427+
for (const key of resolvedKeys) {
428+
deferredFields.delete(key);
429+
}
430+
// and delete map if empty
431+
if (deferredFields.size === 0) {
432+
leftOver.missingFieldsParentDeferredMap.delete(leftOverParent);
433+
}
400434
}
401435
}
402436

0 commit comments

Comments
 (0)