-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: GraphQL execution for
@defer
support (apollographql/apollo…
- Loading branch information
1 parent
22e0034
commit 90ab76b
Showing
11 changed files
with
683 additions
and
82 deletions.
There are no files selected for viewing
138 changes: 138 additions & 0 deletions
138
Sources/ApolloCodegenLib/Templates/DeferredFragmentsMetadataTemplate.swift
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,138 @@ | ||
import GraphQLCompiler | ||
import IR | ||
import TemplateString | ||
|
||
struct DeferredFragmentsMetadataTemplate { | ||
|
||
let operation: IR.Operation | ||
let config: ApolloCodegen.ConfigurationContext | ||
let renderAccessControl: () -> String | ||
|
||
init( | ||
operation: IR.Operation, | ||
config: ApolloCodegen.ConfigurationContext, | ||
renderAccessControl: @autoclosure @escaping () -> String | ||
) { | ||
self.operation = operation | ||
self.config = config | ||
self.renderAccessControl = renderAccessControl | ||
} | ||
|
||
// MARK: Templates | ||
|
||
/// Renders metadata definitions for the deferred fragments of an Operation. | ||
/// | ||
/// - Returns: The `TemplateString` for the deferred fragments metadata definitions. | ||
func render() -> TemplateString { | ||
let deferredFragmentPathTypeInfo = DeferredFragmentsPathTypeInfo( | ||
from: operation.rootField.selectionSet.selections | ||
) | ||
guard !deferredFragmentPathTypeInfo.isEmpty else { return "" } | ||
|
||
return """ | ||
// MARK: Deferred Fragment Metadata | ||
\(renderAccessControl())extension \(operation.generatedDefinitionName) { | ||
\(DeferredFragmentIdentifiersTemplate(deferredFragmentPathTypeInfo)) | ||
\(DeferredFragmentsPropertyTemplate(deferredFragmentPathTypeInfo)) | ||
} | ||
""" | ||
} | ||
|
||
fileprivate func DeferredFragmentIdentifiersTemplate( | ||
_ deferredFragmentPathTypeInfo: [DeferredPathTypeInfo] | ||
) -> TemplateString { | ||
""" | ||
enum DeferredFragmentIdentifiers { | ||
\(deferredFragmentPathTypeInfo.map { | ||
return """ | ||
static let \($0.deferCondition.label) = DeferredFragmentIdentifier(label: \"\($0.deferCondition.label)\", fieldPath: [\ | ||
\($0.path.map { "\"\($0)\"" }, separator: ", ")\ | ||
]) | ||
""" | ||
}, separator: "\n") | ||
} | ||
""" | ||
} | ||
|
||
fileprivate func DeferredFragmentsPropertyTemplate( | ||
_ deferredFragmentPathTypeInfo: [DeferredPathTypeInfo] | ||
) -> TemplateString { | ||
""" | ||
static var deferredFragments: [DeferredFragmentIdentifier: any \(config.ApolloAPITargetName).SelectionSet.Type]? {[ | ||
\(deferredFragmentPathTypeInfo.map { | ||
return """ | ||
DeferredFragmentIdentifiers.\($0.deferCondition.label): \($0.typeName).self, | ||
""" | ||
}, separator: "\n") | ||
]} | ||
""" | ||
} | ||
|
||
// MARK: Helpers | ||
|
||
fileprivate struct DeferredPathTypeInfo { | ||
let path: [String] | ||
let deferCondition: CompilationResult.DeferCondition | ||
let typeName: String | ||
} | ||
|
||
fileprivate func DeferredFragmentsPathTypeInfo( | ||
from directSelections: DirectSelections?, | ||
path: [String] = [] | ||
) -> [DeferredPathTypeInfo] { | ||
guard let directSelections, !directSelections.isEmpty else { return [] } | ||
|
||
var deferredPathTypeInfo: [DeferredPathTypeInfo] = [] | ||
|
||
for field in directSelections.fields.values { | ||
if let field = field as? EntityField { | ||
let fieldPath = path + [(field.alias ?? field.name)] | ||
deferredPathTypeInfo.append(contentsOf: | ||
DeferredFragmentsPathTypeInfo(from: field.selectionSet.selections, path: fieldPath) | ||
) | ||
} | ||
} | ||
|
||
for fragment in directSelections.inlineFragments.values { | ||
if let deferCondition = fragment.typeInfo.deferCondition { | ||
let selectionSetName = SelectionSetNameGenerator.generatedSelectionSetName( | ||
for: fragment.typeInfo, | ||
format: .omittingRoot, | ||
pluralizer: config.pluralizer | ||
) | ||
|
||
deferredPathTypeInfo.append(DeferredPathTypeInfo( | ||
path: path, | ||
deferCondition: deferCondition, | ||
typeName: "Data.\(selectionSetName)" | ||
)) | ||
} | ||
|
||
deferredPathTypeInfo.append(contentsOf: | ||
DeferredFragmentsPathTypeInfo(from: fragment.selectionSet.selections, path: path) | ||
) | ||
} | ||
|
||
for fragment in directSelections.namedFragments.values { | ||
if let deferCondition = fragment.typeInfo.deferCondition { | ||
deferredPathTypeInfo.append(DeferredPathTypeInfo( | ||
path: path, | ||
deferCondition: deferCondition, | ||
typeName: fragment.definition.name.asFragmentName | ||
)) | ||
} | ||
|
||
deferredPathTypeInfo.append(contentsOf: | ||
DeferredFragmentsPathTypeInfo( | ||
from: fragment.fragment.rootField.selectionSet.selections, | ||
path: path | ||
) | ||
) | ||
} | ||
|
||
return deferredPathTypeInfo | ||
} | ||
} |
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
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
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.