Skip to content

Commit e602d6d

Browse files
feat: support fragment parsing in parseFieldNodes
1 parent c7ed50a commit e602d6d

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

packages/query-graphql/src/decorators/graphql-resolve-info.utils.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import {
2-
ASTNode,
3-
DirectiveNode,
2+
type ASTNode,
3+
type DirectiveNode,
4+
type GraphQLField,
5+
GraphQLUnionType,
6+
Kind,
47
getArgumentValues,
58
getNamedType,
6-
GraphQLField,
7-
GraphQLUnionType,
8-
isCompositeType,
9-
Kind
9+
isCompositeType
1010
} from 'graphql'
1111

12-
import type { CursorConnectionType, OffsetConnectionType } from '../types'
13-
import type { RelationDescriptor } from './relation.decorator'
1412
import type { QueryResolveFields, QueryResolveTree, SelectRelation } from '@ptc-org/nestjs-query-core'
1513
import type { GraphQLCompositeType, GraphQLResolveInfo as ResolveInfo, SelectionNode } from 'graphql'
14+
import type { CursorConnectionType, OffsetConnectionType } from '../types'
15+
import type { RelationDescriptor } from './relation.decorator'
1616

1717
/**
1818
* Parts based of https://github.com/graphile/graphile-engine/blob/master/packages/graphql-parse-resolve-info/src/index.ts
@@ -60,6 +60,27 @@ function getDirectiveResults(fieldNode: SelectionNode, info: ResolveInfo) {
6060
}, directiveResult)
6161
}
6262

63+
function inlineFragments(nodes: ReadonlyArray<SelectionNode>, resolveInfo: ResolveInfo): SelectionNode[] {
64+
return nodes.flatMap((ast) => {
65+
if (ast.kind !== Kind.FRAGMENT_SPREAD) return ast
66+
67+
if (ast.directives?.length) {
68+
const { shouldInclude, shouldSkip } = getDirectiveResults(ast, resolveInfo)
69+
// field/fragment is not included if either the @skip condition is true or the @include condition is false
70+
// https://facebook.github.io/graphql/draft/#sec--include
71+
if (shouldSkip || !shouldInclude) {
72+
return []
73+
}
74+
}
75+
76+
const fragment = resolveInfo.fragments[ast.name.value]
77+
if (fragment) {
78+
return inlineFragments(fragment.selectionSet.selections, resolveInfo)
79+
}
80+
return []
81+
})
82+
}
83+
6384
function parseFieldNodes<DTO>(
6485
inASTs: ReadonlyArray<SelectionNode> | SelectionNode,
6586
resolveInfo: ResolveInfo,
@@ -68,16 +89,7 @@ function parseFieldNodes<DTO>(
6889
): QueryResolveTree<DTO> | QueryResolveFields<DTO> {
6990
const asts: ReadonlyArray<SelectionNode> = Array.isArray(inASTs) ? inASTs : [inASTs]
7091

71-
const astsWithInlinedFragments = asts.flatMap(ast => {
72-
if (ast.kind === Kind.FRAGMENT_SPREAD) {
73-
const fragment = resolveInfo.fragments[ast.name.value];
74-
if (fragment) {
75-
return fragment.selectionSet.selections;
76-
}
77-
return [];
78-
}
79-
return ast;
80-
})
92+
const astsWithInlinedFragments = inlineFragments(asts, resolveInfo)
8193

8294
return astsWithInlinedFragments.reduce((tree, fieldNode) => {
8395
let name: string

0 commit comments

Comments
 (0)