-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
minimizes changes to CollectFields a la #3982 but still creates a single memoized incremental field plan per list item.
- Loading branch information
Showing
5 changed files
with
272 additions
and
302 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import { getBySet } from '../jsutils/getBySet.js'; | ||
import { isSameSet } from '../jsutils/isSameSet.js'; | ||
|
||
import type { FieldDetails } from './collectFields.js'; | ||
|
||
export interface DeferUsage { | ||
label: string | undefined; | ||
ancestors: ReadonlyArray<Target>; | ||
} | ||
|
||
export const NON_DEFERRED_TARGET_SET: TargetSet = new Set<Target>([undefined]); | ||
|
||
export type Target = DeferUsage | undefined; | ||
export type TargetSet = ReadonlySet<Target>; | ||
export type DeferUsageSet = ReadonlySet<DeferUsage>; | ||
|
||
export interface FieldGroup { | ||
fields: ReadonlyArray<FieldDetails>; | ||
targets?: TargetSet | undefined; | ||
knownTargets?: TargetSet | undefined; | ||
} | ||
|
||
export type GroupedFieldSet = Map<string, FieldGroup>; | ||
|
||
export interface NewGroupedFieldSetDetails { | ||
groupedFieldSet: GroupedFieldSet; | ||
shouldInitiateDefer: boolean; | ||
} | ||
|
||
export function buildFieldPlan( | ||
fields: Map<string, ReadonlyArray<FieldDetails>>, | ||
parentTargets = NON_DEFERRED_TARGET_SET, | ||
knownTargets = NON_DEFERRED_TARGET_SET, | ||
): { | ||
groupedFieldSet: GroupedFieldSet; | ||
newGroupedFieldSetDetailsMap: Map<DeferUsageSet, NewGroupedFieldSetDetails>; | ||
newDeferUsages: ReadonlyArray<DeferUsage>; | ||
} { | ||
const newDeferUsages: Set<DeferUsage> = new Set<DeferUsage>(); | ||
const newKnownTargets = new Set<Target>(knownTargets); | ||
|
||
const groupedFieldSet = new Map< | ||
string, | ||
{ fields: Array<FieldDetails>; targets: TargetSet; knownTargets: TargetSet } | ||
>(); | ||
|
||
const newGroupedFieldSetDetailsMap = new Map< | ||
DeferUsageSet, | ||
{ | ||
groupedFieldSet: Map< | ||
string, | ||
{ | ||
fields: Array<FieldDetails>; | ||
targets: TargetSet; | ||
knownTargets: TargetSet; | ||
} | ||
>; | ||
shouldInitiateDefer: boolean; | ||
} | ||
>(); | ||
|
||
const map = new Map< | ||
string, | ||
{ targetSet: TargetSet; fieldDetailsList: ReadonlyArray<FieldDetails> } | ||
>(); | ||
for (const [responseKey, fieldDetailsList] of fields) { | ||
const targetSet = new Set<Target>(); | ||
for (const fieldDetails of fieldDetailsList) { | ||
const target = fieldDetails.deferUsage; | ||
targetSet.add(target); | ||
if (!knownTargets.has(target)) { | ||
// all targets that are not known must be defined | ||
newDeferUsages.add(target as DeferUsage); | ||
} | ||
newKnownTargets.add(target); | ||
} | ||
map.set(responseKey, { targetSet, fieldDetailsList }); | ||
} | ||
|
||
for (const [responseKey, { targetSet, fieldDetailsList }] of map) { | ||
const maskingTargetList: Array<Target> = []; | ||
for (const target of targetSet) { | ||
if ( | ||
target === undefined || | ||
target.ancestors.every((ancestor) => !targetSet.has(ancestor)) | ||
) { | ||
maskingTargetList.push(target); | ||
} | ||
} | ||
|
||
const maskingTargets: TargetSet = new Set<Target>(maskingTargetList); | ||
if (isSameSet(maskingTargets, parentTargets)) { | ||
let fieldGroup = groupedFieldSet.get(responseKey); | ||
if (fieldGroup === undefined) { | ||
fieldGroup = { | ||
fields: [], | ||
targets: maskingTargets, | ||
knownTargets: newKnownTargets, | ||
}; | ||
groupedFieldSet.set(responseKey, fieldGroup); | ||
} | ||
fieldGroup.fields.push(...fieldDetailsList); | ||
continue; | ||
} | ||
|
||
let newGroupedFieldSetDetails = getBySet( | ||
newGroupedFieldSetDetailsMap, | ||
maskingTargets, | ||
); | ||
let newGroupedFieldSet; | ||
if (newGroupedFieldSetDetails === undefined) { | ||
newGroupedFieldSet = new Map< | ||
string, | ||
{ | ||
fields: Array<FieldDetails>; | ||
targets: TargetSet; | ||
knownTargets: TargetSet; | ||
} | ||
>(); | ||
|
||
newGroupedFieldSetDetails = { | ||
groupedFieldSet: newGroupedFieldSet, | ||
shouldInitiateDefer: maskingTargetList.some( | ||
(deferUsage) => !parentTargets.has(deferUsage), | ||
), | ||
}; | ||
newGroupedFieldSetDetailsMap.set( | ||
// all new grouped field sets must not contain the initial result as a target | ||
maskingTargets as DeferUsageSet, | ||
newGroupedFieldSetDetails, | ||
); | ||
} else { | ||
newGroupedFieldSet = newGroupedFieldSetDetails.groupedFieldSet; | ||
} | ||
let fieldGroup = newGroupedFieldSet.get(responseKey); | ||
if (fieldGroup === undefined) { | ||
fieldGroup = { | ||
fields: [], | ||
targets: maskingTargets, | ||
knownTargets: newKnownTargets, | ||
}; | ||
newGroupedFieldSet.set(responseKey, fieldGroup); | ||
} | ||
fieldGroup.fields.push(...fieldDetailsList); | ||
} | ||
|
||
return { | ||
groupedFieldSet, | ||
newGroupedFieldSetDetailsMap, | ||
newDeferUsages: Array.from(newDeferUsages), | ||
}; | ||
} |
Oops, something went wrong.