I am trying to set up a multi-module setup where G...
# apollo-kotlin
j
I am trying to set up a multi-module setup where GraphQL fragments/queries are co-located with the features they are used by... I am using Apollo 4.0.0. Do I need to declare the dependency both ways to ensure that it finds everything? This seems strange to me, and wasn't clearly laid out in the multi-module documentation.
Copy code
// feature/feature1/build.gradle.kts
apollo {
  service("service") {
    ...
    dependsOn(project(":core:api"))
  }
}

// core/api/build.gradle.kts
apollo {
  service("service") {
    ...
    isADependencyOf(project(":feature:feature1"))
  }
}
s
Might it be that you need
dependsOn(..., bidirectional = true)
?
j
Hmm, maybe. I was unclear what that would accomplish. It seemed more like a performance enhancement than an actual dependency declaration.
a
It’s intentional to ensure types in the schema aren’t generated multiple times in a multi module project
This section seems pretty clear to me but maybe I’m so deep into it all it makes sense to me
m
I’m actually revisiting the multi-module documentation right now. I would have expected that by default all types get generated in the schema module and you don’t need the double dependency (so it’d be an optimization indeed)
j
I was expecting that too. This is what happens when I try to build without
isADependencyOf
Copy code
Could not determine the dependencies of task ':core:units:generateTraction-apiApolloSources'.
> Could not resolve all task dependencies for configuration ':core:units:apolloTraction-apiCodegenMetadataResolvable'.
   > Could not resolve project :core:traction-api.
     Required by:
         project :core:units
      > No matching variant of project :core:traction-api was found. The consumer was configured to find a component for use during 'CodegenMetadata', as well as attribute 'com.apollographql.service' with value 'traction-api', attribute 'com.apollographql.direction' with value 'Upstream' but:
m
Let me see if I can reproduce that
At least in a simple use case it seems to work: https://github.com/martinbonnin/test-multimodule
IIUC, your modules are: • feature:
:core:units
• schema:
:core:traction-api
?
Can you share the full message you have after
but:
?
j
I actually have three modules right now,
:core:units
,
:feature:import-queue
, and then the schema,
:core:traction-api
. This is a slow migration 😅
Here's the rest of the error:
Copy code
Could not determine the dependencies of task ':core:units:generateTraction-apiApolloSources'.
> Could not resolve all task dependencies for configuration ':core:units:apolloTraction-apiCodegenMetadataResolvable'.
   > Could not resolve project :core:traction-api.
     Required by:
         project :core:units
      > No matching variant of project :core:traction-api was found. The consumer was configured to find a component for use during 'CodegenMetadata', as well as attribute 'com.apollographql.service' with value 'traction-api', attribute 'com.apollographql.direction' with value 'Upstream' but:
          - Variant '(ios_arm64, ios_simulator_arm64)CInteropApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-commonized-cinterop' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'apolloTraction-apiOtherOptionsConsumable' capability TractionMobile.core:traction-api:unspecified declares a component, as well as attribute 'com.apollographql.direction' with value 'Upstream', attribute 'com.apollographql.service' with value 'traction-api':
              - Incompatible because this component declares a component for use during 'OtherOptions' and the consumer needed a component for use during 'CodegenMetadata'
          - Variant 'debugApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during compile-time and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'debugRuntimeElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during runtime and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'debugSourcesElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during runtime and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosArm64ApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-api' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosArm64CInteropApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-cinterop' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosArm64MetadataElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-metadata' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosArm64SourcesElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-runtime' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosSimulatorArm64ApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-api' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosSimulatorArm64CInteropApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-cinterop' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosSimulatorArm64MetadataElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-metadata' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'iosSimulatorArm64SourcesElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-runtime' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'metadataApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-metadata' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'metadataSourcesElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during 'kotlin-runtime' and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'releaseApiElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during compile-time and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'releaseRuntimeElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during runtime and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
          - Variant 'releaseSourcesElements' capability TractionMobile.core:traction-api:unspecified:
              - Incompatible because this component declares a component for use during runtime and the consumer needed a component for use during 'CodegenMetadata'
              - Other compatible attributes:
                  - Doesn't say anything about com.apollographql.direction (required 'Upstream')
                  - Doesn't say anything about com.apollographql.service (required 'traction-api')
I was getting this even before I added
:core:units
m
There’s no Apollo outgoing variant there. Maybe there’s no
generateApolloMetadata
in your
:core:traction-api
?
generateApolloMetadata
is the thing that marks a module as the schema module for Apollo.
isADependencyOf()
sets it automatically but without this I’m not sure it’s completely possible to find the schema module
j
Oh, that might explain why
isADependencyOf
fixes it. I wasn't setting that property in my schema module.
It doesn't like the
field
reference. If I change it to use the specific type, e.g. `AssociationType.`field`` , that removes the error. But of course that gets overridden.
m
Ah that might be another issue
Maybe
targetName
can help here
I'm on mobile right now but I can dive a bit more later
j
It seems that
generateApolloMetadata
generates a bunch of types even if you don't use/reference them. I.e. there are things from our schema but which the app doesn't use. That's causing an issue with Kotlin. But if I remove that, then they don't get generated and thus it compiles. But then I have the issue with the outgoing variant.
The conflict is with generator producing an enum case with the name 'field', which it tries to escape, but Kotlin still wants to resolve it to the closer reference in the scope of an underlying field for the property.
b
for the
field
issue you can add this on a file named
extra.graphqls
next to your schema:
Copy code
extend enum AssociationType {
  field @targetName(name: "_field")
}
🙏 1
☝️ 1
👍 1
j
Thanks @bod. That fixed it. I am now able to build without
isADependencyOf
and with
generateApolloMetadata.set(true)
I am still slightly concerned that it's generating far more types in the
type
package than it needs to... I suppose that is unavoidable though?
m
I am still slightly concerned that it’s generating far more types in the
type
package than it needs to... I suppose that is unavoidable though?
Indeed. There’s no silver bullet. It’s either: • Generating all types • Tracking the types manually and listing them 1 by 1 in
alwaysGenerateTypesMatching.set(listOf("Type1", "Type2", ...)
• Tracking the types automatically and ◦ using
isADependencyOf()
◦ or using experimental
bidirectional = true
and no project isolation
j
Okay, that is good to know. I will stick with
isADependencyOf
for now then. Thanks for the help!
m
Sure thing!