Skip to content

Commit 7c4be08

Browse files
committed
wip: registerRootNode stuff
1 parent ce146c3 commit 7c4be08

File tree

5 files changed

+30
-6
lines changed

5 files changed

+30
-6
lines changed

spec/dev/model/simple.graphqls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type Movie @rootEntity {
7171
type Director @rootEntity {
7272
name: String
7373
movies: [Movie] @relation(inverseOf: "director")
74+
allMissions: [Mission] @collect(path: "movies.heroes.missions", aggregate: DISTINCT)
7475
}
7576

7677
"A description of a hero suit"

src/schema-generation/field-nodes.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,20 @@ import { GraphQLOffsetDateTime } from '../schema/scalars/offset-date-time';
2727
import { getScalarFilterValueNode } from './filter-input-types/filter-fields';
2828
import { and } from './utils/input-types';
2929

30+
export interface CreateFieldNodeOptions {
31+
readonly skipNullFallbackForEntityExtensions?: boolean;
32+
readonly rootEntityVar?: VariableQueryNode;
33+
34+
/**
35+
* Call this on collect fields that traverse root entities to store a reference to the root entity in the stack
36+
*/
37+
readonly registerRootNode?: (rootNode: QueryNode) => void;
38+
}
39+
3040
export function createFieldNode(
3141
field: Field,
3242
sourceNode: QueryNode,
33-
options: {
34-
skipNullFallbackForEntityExtensions?: boolean;
35-
rootEntityVar?: VariableQueryNode;
36-
} = {},
43+
options: CreateFieldNodeOptions = {},
3744
): QueryNode {
3845
// make use of the fact that field access on non-objects is NULL, so that type checks for OBJECT are redundant
3946
// this e.g. reverses the effect of the isEntityExtensionType check below

src/schema-generation/output-type-generator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ export class OutputTypeGenerator {
256256

257257
return createFieldNode(field, sourceNode, {
258258
skipNullFallbackForEntityExtensions: true,
259+
registerRootNode: (rootNode) => rootHelperResult.registerRootNode(rootNode),
259260
});
260261
}
261262

src/schema-generation/query-node-object-type/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { FieldSelection } from '../../graphql/query-distiller';
77
*
88
* There usually is a 1:1 relationship between a FieldSelection/FieldRequest and the SelectionToken. However, instances
99
* of a FieldSelection do not convey an identity per se. Usage of the SelectionToken class makes it clear that it's not
10-
* taken for its values bot for the identity within an execution. This is a useful property for caches and external
10+
* taken for its values but for the identity within an execution. This is a useful property for caches and external
1111
* state management.
1212
*/
1313
export class SelectionToken {

src/schema-generation/root-field-helper.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,20 @@ export interface ProcessFieldResult {
1414
* If the RootFieldHelper can already resolve this fields, this will be populated with the value.
1515
*/
1616
readonly resultNode: QueryNode | undefined;
17+
18+
/**
19+
* Call this on collect fields that traverse root entities to store a reference to the root entity in the stack
20+
*/
21+
registerRootNode(rootNode: QueryNode): void;
1722
}
1823

1924
interface HierarchyStackFrame {
2025
readonly currentEntityNode?: QueryNode;
2126
readonly parentEntityFrame?: HierarchyStackFrame;
27+
2228
// keep root explicitly because sometimes, we might have the root entity, but not the parent entity
23-
readonly rootEntityNode?: QueryNode;
29+
// set by registerRootNode()
30+
rootEntityNode?: QueryNode;
2431
}
2532

2633
export class RootFieldHelper {
@@ -124,6 +131,14 @@ export class RootFieldHelper {
124131

125132
return {
126133
resultNode: this.tryResolveField(field, hierarchyFrame),
134+
registerRootNode(rootNode: QueryNode) {
135+
if (hierarchyFrame.rootEntityNode) {
136+
throw new Error(
137+
`Root query node already registered for field "${field.declaringType.name}.${field.name}"`,
138+
);
139+
}
140+
hierarchyFrame.rootEntityNode = rootNode;
141+
},
127142
};
128143
}
129144

0 commit comments

Comments
 (0)