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

InputObjects generated with incorrect getter/setter key #2858

Closed
Austinpayne opened this issue Feb 28, 2023 · 10 comments · Fixed by #2996
Closed

InputObjects generated with incorrect getter/setter key #2858

Austinpayne opened this issue Feb 28, 2023 · 10 comments · Fixed by #2996
Assignees
Labels
bug Generally incorrect behavior codegen Issues related to or arising from code generation planned-next Slated to be included in the next release
Milestone

Comments

@Austinpayne
Copy link

Austinpayne commented Feb 28, 2023

Summary

I'm having a issue with a custom input that results in different string keys being generated for InputObjects in the init and the associated getter/setter. For example:

// @generated
// This file was automatically generated and should not be edited.

import ApolloAPI

public extension API {
  struct EquipmentFilterInput: InputObject {
    public private(set) var __data: InputDict

    public init(_ data: InputDict) {
      __data = data
    }

    public init(
      iD: GraphQLNullable<String> = nil
    ) {
      __data = InputDict([
        "ID": iD
      ])
    }

    public var iD: GraphQLNullable<String> {
      get { __data["iD"] }
      set { __data["iD"] = newValue }
    }
}

Note that the __data in the init uses the string key "ID" while the var iD getter/setter uses iD.

Version

1.0.7 (I also saw it on 1.0.5)

Steps to reproduce the behavior

The above issue was seen using the following operation definitions:

fragment EquipmentFields on Equipment {
    __typename,
    ID,
}

query ReadEquipments($where: EquipmentFilterInput) {
    equipments(where: $where) {
        ...EquipmentFields
    }
}

Where EquipmentFilterInput is defined as the following in the schema:

input EquipmentFilterInput {
  ID: String
}

Logs

The above bug results in the query being malformed and returning errors like

[Variable "$where" got invalid value "{"iD":{"isEqualTo":"E4600CC4-0FAC-40F7-8EC7-5CE65AF5B05F"}}".
In field "iD": Unknown field.]

If I manually change __data["iD"] to __data["ID"] then queries are successful.

Anything else?

No response

@Austinpayne Austinpayne added bug Generally incorrect behavior needs investigation labels Feb 28, 2023
@fabiojgrocha
Copy link

fabiojgrocha commented Mar 1, 2023

Found the same issue, on both versions. This also causes the apps to crash if you attempt to use the getter as Apollo will force cast nil to String.

Issue seems to be located here:

escapeIf(in: SwiftKeywords.InputParameterNamesToEscape).firstLowercased

@calvincestari
Copy link
Member

Thanks for reporting this @Austinpayne, we'll get it resolved in the next release.

@calvincestari calvincestari added codegen Issues related to or arising from code generation planned-next Slated to be included in the next release and removed needs investigation labels Mar 2, 2023
@calvincestari calvincestari added this to the Patch Releases (1.0.x) milestone Mar 2, 2023
@calvincestari calvincestari self-assigned this Mar 3, 2023
@Austinpayne
Copy link
Author

Thanks for reporting this @Austinpayne, we'll get it resolved in the next release.

Thank you @calvincestari! I appreciate your responsiveness, always very impressive!

@calvincestari calvincestari removed the planned-next Slated to be included in the next release label Mar 31, 2023
@calvincestari calvincestari added the planned-next Slated to be included in the next release label May 1, 2023
@BobaFetters BobaFetters linked a pull request May 4, 2023 that will close this issue
@alkincakiralar1996
Copy link

alkincakiralar1996 commented May 8, 2023

Hello @calvincestari @BobaFetters, I'm experiencing this issue too.

I just wanted to show my input object in case it might be helpful for the solution.

However, I forked the fix/generated-getter-setter-case branch and run the ./apollo-ios-cli generate command to check if it's solved or not but still getting the same generated code as below.

When I manually change set { __data["aND"] = newValue } to set { __data["AND"] = newValue } query works.

// @generated
// This file was automatically generated and should not be edited.

import ApolloAPI

public extension API {
  /// Dynamic WHERE conditions for the `where` argument on the query `listings_with_pagination`.
  struct QueryListingsWithPaginationWhereWhereConditions: InputObject {
    public private(set) var __data: InputDict

    public init(_ data: InputDict) {
      __data = data
    }

    public init(
      column: GraphQLNullable<GraphQLEnum<ListingColumn>> = nil,
      `operator`: GraphQLNullable<GraphQLEnum<SQLOperator>> = nil,
      value: GraphQLNullable<Mixed> = nil,
      aND: GraphQLNullable<[QueryListingsWithPaginationWhereWhereConditions]> = nil,
      oR: GraphQLNullable<[QueryListingsWithPaginationWhereWhereConditions]> = nil,
      hAS: GraphQLNullable<QueryListingsWithPaginationWhereWhereConditionsRelation> = nil
    ) {
      __data = InputDict([
        "column": column,
        "operator": `operator`,
        "value": value,
        "AND": aND,
        "OR": oR,
        "HAS": hAS
      ])
    }

    /// The column that is used for the condition.
    public var column: GraphQLNullable<GraphQLEnum<ListingColumn>> {
      get { __data["column"] }
      set { __data["column"] = newValue }
    }

    /// The operator that is used for the condition.
    public var `operator`: GraphQLNullable<GraphQLEnum<SQLOperator>> {
      get { __data["operator"] }
      set { __data["operator"] = newValue }
    }

    /// The value that is used for the condition.
    public var value: GraphQLNullable<Mixed> {
      get { __data["value"] }
      set { __data["value"] = newValue }
    }

    /// A set of conditions that requires all conditions to match.
    public var aND: GraphQLNullable<[QueryListingsWithPaginationWhereWhereConditions]> {
      get { __data["aND"] }
      set { __data["aND"] = newValue }
    }

    /// A set of conditions that requires at least one condition to match.
    public var oR: GraphQLNullable<[QueryListingsWithPaginationWhereWhereConditions]> {
      get { __data["oR"] }
      set { __data["oR"] = newValue }
    }

    /// Check whether a relation exists. Extra conditions or a minimum amount can be applied.
    public var hAS: GraphQLNullable<QueryListingsWithPaginationWhereWhereConditionsRelation> {
      get { __data["hAS"] }
      set { __data["hAS"] = newValue }
    }
  }

}

@BobaFetters
Copy link
Member

@alkincakiralar1996 can you provide a sample schema and operation definitions that I could use to test your case and see if further changes are required to resolve the issue?

@alkincakiralar1996
Copy link

Hi @BobaFetters, thanks for the quick reply.

I'll put the piece of code from the schema that can be related to "QueryListingsWithPaginationWhereWhereConditions" below. We have a query that returns some kind of model data that can be filterable. We are using this "QueryListingsWithPaginationWhereWhereConditions" type inside of that query as a where parameter.

Do you want me to signify another thing that helps you to test this case?

{
                  "name": "where",
                  "description": null,
                  "type": {
                    "kind": "INPUT_OBJECT",
                    "name": "QueryListingsWithPaginationWhereWhereConditions",
                    "ofType": null
                  },
                  "defaultValue": null
                },
{
          "kind": "INPUT_OBJECT",
          "name": "QueryListingsWithPaginationWhereWhereConditions",
          "description": "Dynamic WHERE conditions for the `where` argument on the query `listings_with_pagination`.",
          "fields": null,
          "inputFields": [
            {
              "name": "column",
              "description": "The column that is used for the condition.",
              "type": {
                "kind": "ENUM",
                "name": "ListingColumn",
                "ofType": null
              },
              "defaultValue": null
            },
            {
              "name": "operator",
              "description": "The operator that is used for the condition.",
              "type": { "kind": "ENUM", "name": "SQLOperator", "ofType": null },
              "defaultValue": "EQ"
            },
            {
              "name": "value",
              "description": "The value that is used for the condition.",
              "type": { "kind": "SCALAR", "name": "Mixed", "ofType": null },
              "defaultValue": null
            },
            {
              "name": "AND",
              "description": "A set of conditions that requires all conditions to match.",
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "INPUT_OBJECT",
                    "name": "QueryListingsWithPaginationWhereWhereConditions",
                    "ofType": null
                  }
                }
              },
              "defaultValue": null
            },
            {
              "name": "OR",
              "description": "A set of conditions that requires at least one condition to match.",
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "INPUT_OBJECT",
                    "name": "QueryListingsWithPaginationWhereWhereConditions",
                    "ofType": null
                  }
                }
              },
              "defaultValue": null
            },
            {
              "name": "HAS",
              "description": "Check whether a relation exists. Extra conditions or a minimum amount can be applied.",
              "type": {
                "kind": "INPUT_OBJECT",
                "name": "QueryListingsWithPaginationWhereWhereConditionsRelation",
                "ofType": null
              },
              "defaultValue": null
            }
          ],
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },

@BobaFetters
Copy link
Member

BobaFetters commented May 8, 2023

@alkincakiralar1996 when you forked the fix/generated-getter-setter-case branch, did you also build an apollo-ios-cli executable from that code to use for your ./apollo-ios-cli generate command? If not then none of the changes in the branch would have been used for your code generation. From what I see the code in the pending PR should resolve this issue.

@alkincakiralar1996
Copy link

I was just researching this, yes you're right I still use the old apollo-ios-cli. How can I build a new apollo-ios-cli executable ?

@alkincakiralar1996
Copy link

Yes, now it works. Sorry for the misunderstanding, thanks for your patience and your effort.

@calvincestari
Copy link
Member

I was just researching this, yes you're right I still use the old apollo-ios-cli. How can I build a new apollo-ios-cli executable ?

The makefile in the root of the repo has a command to build it - make build-cli. You'll have to dig into the .build folder to access it though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Generally incorrect behavior codegen Issues related to or arising from code generation planned-next Slated to be included in the next release
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants