Skip to content

[Swift] Codegen for input types has non-deterministic order #1599

@AttilaTheFun

Description

@AttilaTheFun

I've been extremely frustrated with the fact that the order of codegen'd initializer parameters for input objects appears to be nondeterministic. I believe the order for regular fragments is the order of the fields in the query, but for input objects, there is no obvious order. E.g.:

mutation CreateSession($request: CreateSessionRequest!) {
  createSession(request: $request) {
    session {
      ...allSessionFields
    }
  }
}

If CreateSessionRequest has two arguments, say a userID and a token, sometimes I get:

CreateSessionRequest(userID:token:) and other times I get CreateSessionRequest(token:userID)

Every time I update my schema, and refetch the schema from my server using the CLI, then re-codegen from that schema, a bunch of parameters for my requests change order.

The auto-fixits often only reorder the parameter names and not the values making them dangerous. This means that every time I update the schema, when I codegen I have to go fix how I call these initializers in many places. At least I'm able to shield some of my code from this liability by providing a consistent API which abstracts away Apollo using domain models, but it's still painful.

I've gone so far as writing a script to alphabetize the fetched schema (which helps reduce noise in commits), but the generated code still seems to be nondeterministic and the parameters do not seem to follow any discernible ordering.

Example:

In my alphabetized schema, you can see that the fields of EditableUserFields are in the correct order:

      {
        "description": "", 
        "enumValues": null, 
        "fields": null, 
        "inputFields": [
          {
            "defaultValue": null, 
            "description": "", 
            "name": "biography", 
            "type": {
              "kind": "SCALAR", 
              "name": "String", 
              "ofType": null
            }
          }, 
          {
            "defaultValue": null, 
            "description": "", 
            "name": "emailAddress", 
            "type": {
              "kind": "NON_NULL", 
              "name": null, 
              "ofType": {
                "kind": "SCALAR", 
                "name": "String", 
                "ofType": null
              }
            }
          }, 
          {
            "defaultValue": null, 
            "description": "", 
            "name": "fullName", 
            "type": {
              "kind": "NON_NULL", 
              "name": null, 
              "ofType": {
                "kind": "SCALAR", 
                "name": "String", 
                "ofType": null
              }
            }
          }, 
          {
            "defaultValue": null, 
            "description": "", 
            "name": "profilePictureURL", 
            "type": {
              "kind": "NON_NULL", 
              "name": null, 
              "ofType": {
                "kind": "SCALAR", 
                "name": "String", 
                "ofType": null
              }
            }
          }, 
          {
            "defaultValue": null, 
            "description": "", 
            "name": "username", 
            "type": {
              "kind": "NON_NULL", 
              "name": null, 
              "ofType": {
                "kind": "SCALAR", 
                "name": "String", 
                "ofType": null
              }
            }
          }, 
          {
            "defaultValue": null, 
            "description": "", 
            "name": "website", 
            "type": {
              "kind": "SCALAR", 
              "name": "String", 
              "ofType": null
            }
          }
        ], 
        "interfaces": null, 
        "kind": "INPUT_OBJECT", 
        "name": "EditableUserFields", 
        "possibleTypes": null
      }, 

However in the generated code, I see this order:

EditableUserFields(biography:,profilePictureUrl:,fullName:,username:, emailAddress:, website:)

Is there a way to address this? Am I holding it wrong? Or do we actually need to fix it on the Apollo end? I'm surprised no one I could find was complaining about this as it seems like it would be a common bugbear for consumers of Apollo, making me think that there's something odd about my setup which is causing this noise.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions