apollographql / apollo-ios

📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.
https://www.apollographql.com/docs/ios/
MIT License
3.88k stars 726 forks source link

codegen: Append type to generated filenames #3354

Closed michaelloo closed 3 months ago

michaelloo commented 8 months ago

Summary

If you have an INPUT_OBJECT type with name Address, and a OBJECT type with the same name Address , you end up with a conflicting filename which causes an Xcode compile issue:

Filename "Address.graphql.swift" used twice: '.../GeneratedFiles/Schema/Objects/Address.graphql.swift' and '.../GeneratedFiles/Schema/InputObjects/Address.graphql.swift'

Screenshot 2024-03-15 at 11 40 49 am

The struct name are ok because they are nested under different levels:

Screenshot 2024-03-15 at 11 40 54 am Screenshot 2024-03-15 at 11 40 59 am

Version

1.9.0

Steps to reproduce the behavior

apollo-codegen-config:

{
  "schemaNamespace" : "GQLSchema",
  "schemaDownload": {
    "downloadMethod": {
        "introspection": {
            "endpointURL": "some.url/graphql",
            "httpMethod": { "POST": {} },
            "includeDeprecatedInputValues": false,
            "outputFormat": "JSON"
        }
    },
    "downloadTimeout": 60,
    "outputPath": "./graphql/"
  },
  "input" : {
    "operationSearchPaths" : ["**/*.graphql"],
    "schemaSearchPaths" : ["**/schema.json"]
  },
  "output" : {
    "testMocks" : { "none" : {} },
    "schemaTypes" : {
      "path" : "./GeneratedFiles",
      "moduleType" : { "embeddedInTarget" : { "name": "XXX" } }
    },
    "operations" : { "inSchemaModule" : {} }
  },
  "options": {
    "cocoapodsCompatibleImportStatements": true,
    "selectionSetInitializers": {
      "localCacheMutations" : true,
      "namedFragments" : true,
      "operations" : true
    }
  }
}

I am unable to give you a full view of the schema unfortunately but here are some snippets of it:

      {
        "kind": "OBJECT",
        "name": "Address",
        "description": null,
        "specifiedByUrl": null,
// ...
      {
        "kind": "OBJECT",
        "name": "XXX_Item",
        "description": null,
        "specifiedByUrl": null,
        "fields": [
          {
            "name": "address",
            "description": "...",
            "args": [],
            "type": {
              "kind": "NON_NULL",
              "name": null,
              "ofType": {
                "kind": "OBJECT",
                "name": "Address",
                "ofType": null
              }
            },
            "isDeprecated": false,
            "deprecationReason": null
          }
        ],
// ...
      {
        "kind": "INPUT_OBJECT",
        "name": "XXX_Input",
        "description": null,
        "specifiedByUrl": null,
        "fields": null,
        "inputFields": [
          {
            "name": "address",
            "description": "address",
            "type": {
              "kind": "NON_NULL",
              "name": null,
              "ofType": {
                "kind": "INPUT_OBJECT",
                "name": "address",
                "ofType": null
              }
            },
            "defaultValue": null,
            "isDeprecated": false,
            "deprecationReason": null
          }
        ],
// ...
      {
        "kind": "INPUT_OBJECT",
        "name": "address",
        "description": null,
        "specifiedByUrl": null,
        "fields": null,
// ...

If I rename one of the conflicting files, then I am able to get through this error, (e.g.: AddressInput).

Logs

No response

Anything else?

Is there a way to specify the output to be in a single file (like it used to be able to do)? Then I can avoid this filename conflict

calvincestari commented 7 months ago

I believe this is a known issue @michaelloo, and unfortunately we don't have a workaround that isn't manual at the moment. Xcode really should just be able to handle this to be honest. A solution that works with codegen may have to be adding a name suffix to each file with what kind it is; AddressInputObject, AddressObject, etc.

michaelloo commented 7 months ago

😢 Ah ok... we'll have a script them to rename the file for now after updating the models, thanks for the response!

michaelloo commented 7 months ago

Hi @calvincestari , on a somewhat related note, what is the suggested approach if we have the same codebase relying on multiple APIs with different GraphQL schemas? Meaning having multiple apollo-codegen-config.json files but the generate code might have filename conflict, e.g.:

error: Filename "SchemaConfiguration.swift" used twice: 'some/path/GeneratedFiles/Schema/SchemaConfiguration.swift' and 'some/other/path/GeneratedFiles/Schema/SchemaConfiguration.swift' (in target 'XXX' from project 'XXX')
calvincestari commented 7 months ago

Apollo iOS is not designed to work with multiple schemas at once and to do so requires a bit of careful configuration.

To resolve the duplicate SchemaConfiguration.swift you'll need to generate the schemas into different targets/packages, I believe that should resolve the issue.

michaelloo commented 7 months ago

I see, we'll get onto that but this isn't an ideal solution so i've opened a separate feature request here 🙏

AnthonyMDev commented 5 months ago

A workaround for this is being implemented currently. See #3283 for more info. Once that is released, you'll be able to change the generated names of these types (including file names) to AddressInputObject and AddressType (or any names you choose).

AnthonyMDev commented 3 months ago

The workaround for this in #3283 has been shipped in 1.13.0. That is now the suggested solution when dealing with this problem in the future. Closing this issue.

github-actions[bot] commented 3 months ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.