Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SelectionSet Codegen __typename fix - Closes #2955 #2983

Merged
merged 2 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ SwiftScripts/.build-**
# Local generated packages we don't need in the main project
Sources/AnimalKingdomAPI/Generated/Package.swift
Sources/AnimalKingdomAPI/Generated/Package.resolved

# Generated js files we don't need committed
Sources/ApolloCodegenLib/Frontend/dist/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions Sources/ApolloCodegenLib/Frontend/CompilationResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ public class CompilationResult: JavaScriptObject {
private enum Constants {
static let LocalCacheMutationDirectiveName = "apollo_client_ios_localCacheMutation"
}
lazy var rootTypes: RootTypeDefinition = self["rootTypes"]

lazy var referencedTypes: [GraphQLNamedType] = self["referencedTypes"]

lazy var operations: [OperationDefinition] = self["operations"]
Expand All @@ -13,6 +15,31 @@ public class CompilationResult: JavaScriptObject {

lazy var schemaDocumentation: String? = self["schemaDocumentation"]

required init(_ jsValue: JSValue, bridge: JavaScriptBridge) {
super.init(jsValue, bridge: bridge)
processRootTypes()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking through the code, and where/how the isRootFieldType was originally used, without piping the new root type data through the pipeline, or updating the GraphQLCompositeType objects later in the pipeline, this seems like a good way to ensure all of the GraphQLCompositeType objects have their isRootFieldType updated before use.

}

private func processRootTypes() {
let typeList = [rootTypes.queryType.name, rootTypes.mutationType?.name, rootTypes.subscriptionType?.name].compactMap { $0 }

operations.forEach { op in
op.rootType.isRootFieldType = typeList.contains(op.rootType.name)
}

fragments.forEach { fragment in
fragment.type.isRootFieldType = typeList.contains(fragment.type.name)
}
}

public class RootTypeDefinition: JavaScriptObject {
lazy var queryType: GraphQLNamedType = self["queryType"]

lazy var mutationType: GraphQLNamedType? = self["mutationType"]

lazy var subscriptionType: GraphQLNamedType? = self["subscriptionType"]
}

public class OperationDefinition: JavaScriptObject, Equatable {
lazy var name: String = self["name"]

Expand Down
5 changes: 2 additions & 3 deletions Sources/ApolloCodegenLib/Frontend/GraphQLSchema.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ public class GraphQLCompositeType: GraphQLNamedType {
"Type - \(name)"
}

var isRootFieldType: Bool {
["Query", "Mutation", "Subscription"].contains(name)
}
var isRootFieldType: Bool = false

}

protocol GraphQLInterfaceImplementingType: GraphQLCompositeType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function filePathForNode(node: ASTNode): string | undefined {
}

export interface CompilationResult {
rootTypes: ir.RootTypeDefinition;
operations: ir.OperationDefinition[];
fragments: ir.FragmentDefinition[];
referencedTypes: GraphQLNamedType[];
Expand All @@ -71,6 +72,12 @@ export function compileToIR(
const fragmentMap = new Map<String, ir.FragmentDefinition>();
const referencedTypes = new Set<GraphQLNamedType>();

const rootTypes: ir.RootTypeDefinition = {
queryType: schema.getQueryType(),
mutationType: schema.getMutationType(),
subscriptionType: schema.getSubscriptionType()
};

for (const definitionNode of document.definitions) {
if (definitionNode.kind !== Kind.OPERATION_DEFINITION) continue;

Expand All @@ -86,7 +93,8 @@ export function compileToIR(
}

return {
operations,
rootTypes: rootTypes,
operations: operations,
fragments: Array.from(fragmentMap.values()),
referencedTypes: Array.from(referencedTypes.values()),
schemaDocumentation: schema.description ?? undefined
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import {
GraphQLCompositeType,
GraphQLInputType,
GraphQLNamedType,
GraphQLObjectType,
GraphQLOutputType,
GraphQLType,
} from "graphql";
import { GraphQLValue } from "./values";

export interface RootTypeDefinition {
queryType: GraphQLNamedType | unknown;
mutationType: GraphQLNamedType | unknown;
subscriptionType: GraphQLNamedType | unknown;
}

export interface OperationDefinition {
name: string;
operationType: OperationType;
Expand Down
7 changes: 7 additions & 0 deletions Sources/ApolloCodegenLib/Frontend/auto_rollup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
output_file="$SCRIPT_DIR/ApolloCodegenFrontendBundle.swift"
$( cd "$SCRIPT_DIR/Javascript" && rollup -c )
minJS=$(cat "$SCRIPT_DIR/dist/ApolloCodegenFrontend.bundle.js")
printf "%s%s%s" "let ApolloCodegenFrontendBundle: String = #\"" "$minJS" "\"#" > $output_file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done!

Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,54 @@ class SelectionSetTemplateTests: XCTestCase {
// then
expect(actual).to(equalLineByLine(expected, atLine: 6, ignoringExtraLines: true))
}

func test__render_selections__givenCustomRootTypes_doesNotGenerateTypenameField() throws {
// given
schemaSDL = """
schema {
query: RootQueryType
mutation: RootMutationType
}

type RootQueryType {
allAnimals: [Animal!]
}

type RootMutationType {
feedAnimal: Animal!
}

type Animal {
FieldName: String!
}
"""

document = """
query TestOperation {
allAnimals {
FieldName
}
}
"""

let expected = """
public static var __selections: [Apollo.Selection] { [
.field("allAnimals", [AllAnimal]?.self),
] }
"""

// when
try buildSubjectAndOperation(cocoapodsImportStatements: true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needing the cocoapodsImportStatements: true. I assume you copied this from another test that happened to be testing part of the codegen template that differs for Cocoapods. There is no harm in this param being set, but I'd remove it, just to keep the scope of the test limited to only what its really testing.

let allAnimals = try XCTUnwrap(
operation[field: "query"] as? IR.EntityField
)

let actual = subject.render(field: allAnimals)
print("Actual Output - \(actual)")

// then
expect(actual).to(equalLineByLine(expected, atLine: 7, ignoringExtraLines: true))
}

// MARK: Selections - Fields

Expand Down