-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial federation support * add apiDump * fix introspection * fix test in CI * use kotlinpoet functions * remove unneeded tests * Revert "fix test in CI" This reverts commit 382630e. * update workflow file * fix enums with KSP2
- Loading branch information
1 parent
75eb863
commit 5838974
Showing
41 changed files
with
1,191 additions
and
311 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Apollo Federation | ||
|
||
Apollo Kotlin Execution supports [Apollo Federation](https://www.apollographql.com/federation). | ||
|
||
To use federation, add the `apollo-execution-federation` artifact to your project: | ||
|
||
```kotlin | ||
dependencies { | ||
// Add the federation dependency | ||
implementation("com.apollographql.execution:apollo-execution-federation:%latest_version%") | ||
} | ||
``` | ||
|
||
## Defining entity keys | ||
|
||
You can define [entity](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/entities/intro) key using the `GraphQLKey` annotation: | ||
|
||
```kotlin | ||
class Product( | ||
@GraphQLKey | ||
val id: String, | ||
val name: String | ||
) | ||
``` | ||
|
||
The `GraphQLKey` annotation is translated at build time into a matching federation `@key` directive: | ||
|
||
```graphql | ||
@key(fields: "id") | ||
type Product { | ||
id: String!, | ||
name: String! | ||
} | ||
``` | ||
|
||
> By adding the annotation on the field definition instead of the type definition, Apollo Kotlin Execution gives you more type safety. | ||
{style="note"} | ||
|
||
## Federation subgraph fields | ||
|
||
Whenever a type containing a `@GraphQLKey` field is present, Apollo Kotlin Execution adds the [federation subgraph fields](https://www.apollographql.com/docs/graphos/reference/federation/subgraph-specific-fields), `_service` and `_entities`: | ||
|
||
```graphql | ||
# an union containing all the federated types in the schema, constructed at build time | ||
union _Entity = Product | ... | ||
# coerced as a JSON object containing '__typename' and all the key fields. | ||
scalar _Any | ||
|
||
type _Service { | ||
sdl: String! | ||
} | ||
|
||
extend type Query { | ||
_entities(representations: [_Any!]!): [_Entity]! | ||
_service: _Service! | ||
} | ||
``` | ||
|
||
## Defining federated resolvers | ||
|
||
In order to support the `_entities` field, federation requires a resolver that can resolve an entity from its key field. | ||
|
||
You can add one by defining a `resolve` function on the companion object: | ||
|
||
```kotlin | ||
class Product( | ||
@GraphQLKey | ||
val id: String, | ||
val name: String | ||
) { | ||
companion object { | ||
fun resolve(id: String): Product { | ||
return products.first { it.id == id } | ||
} | ||
} | ||
} | ||
|
||
val products = listOf( | ||
Product("1", "foo"), | ||
Product("2", "bar") | ||
) | ||
``` | ||
|
||
Just like regular resolvers, the entity resolvers can be suspend and/or have an `ExecutionContext` parameter: | ||
|
||
```kotlin | ||
class Product( | ||
@GraphQLKey | ||
val id: String, | ||
val name: String | ||
) { | ||
companion object { | ||
suspend fun resolve(executionContext: ExecutionContext, id: String): Product { | ||
return executionContext.loader.getProdut(id) | ||
} | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Module apollo-execution-federation | ||
|
10 changes: 10 additions & 0 deletions
10
apollo-execution-federation/api/apollo-execution-federation.api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
public abstract interface annotation class com/apollographql/execution/federation/GraphQLKey : java/lang/annotation/Annotation { | ||
} | ||
|
||
public final class com/apollographql/execution/federation/_AnyCoercing : com/apollographql/execution/Coercing { | ||
public static final field INSTANCE Lcom/apollographql/execution/federation/_AnyCoercing; | ||
public fun deserialize (Ljava/lang/Object;)Ljava/lang/Object; | ||
public fun parseLiteral (Lcom/apollographql/apollo/ast/GQLValue;)Ljava/lang/Object; | ||
public fun serialize (Ljava/lang/Object;)Ljava/lang/Object; | ||
} | ||
|
16 changes: 16 additions & 0 deletions
16
apollo-execution-federation/api/apollo-execution-federation.klib.api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Klib ABI Dump | ||
// Targets: [macosArm64] | ||
// Rendering settings: | ||
// - Signature version: 2 | ||
// - Show manifest properties: true | ||
// - Show declarations: true | ||
|
||
// Library unique name: <com.apollographql.execution:apollo-execution-federation> | ||
final object com.apollographql.execution.federation/_AnyCoercing : com.apollographql.execution/Coercing<kotlin/Any?> { // com.apollographql.execution.federation/_AnyCoercing|null[0] | ||
final fun deserialize(kotlin/Any?): kotlin/Any? // com.apollographql.execution.federation/_AnyCoercing.deserialize|deserialize(kotlin.Any?){}[0] | ||
final fun parseLiteral(com.apollographql.apollo.ast/GQLValue): kotlin/Any? // com.apollographql.execution.federation/_AnyCoercing.parseLiteral|parseLiteral(com.apollographql.apollo.ast.GQLValue){}[0] | ||
final fun serialize(kotlin/Any?): kotlin/Any? // com.apollographql.execution.federation/_AnyCoercing.serialize|serialize(kotlin.Any?){}[0] | ||
} | ||
open annotation class com.apollographql.execution.federation/GraphQLKey : kotlin/Annotation { // com.apollographql.execution.federation/GraphQLKey|null[0] | ||
constructor <init>() // com.apollographql.execution.federation/GraphQLKey.<init>|<init>(){}[0] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import com.gradleup.librarian.gradle.librarianModule | ||
|
||
plugins { | ||
id("org.jetbrains.kotlin.multiplatform") | ||
} | ||
|
||
librarianModule(true) | ||
|
||
kotlin { | ||
jvm() | ||
macosArm64() | ||
|
||
sourceSets { | ||
getByName("commonMain") { | ||
dependencies { | ||
api(libs.apollo.ast) | ||
api(libs.apollo.api) | ||
api(project(":apollo-execution-runtime")) | ||
} | ||
} | ||
|
||
getByName("commonTest") { | ||
dependencies { | ||
implementation(libs.kotlin.test) | ||
} | ||
} | ||
} | ||
} | ||
|
5 changes: 5 additions & 0 deletions
5
...ion-federation/src/commonMain/kotlin/com/apollographql/execution/federation/GraphQLKey.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.apollographql.execution.federation | ||
|
||
|
||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION) | ||
annotation class GraphQLKey |
38 changes: 38 additions & 0 deletions
38
...tion-federation/src/commonMain/kotlin/com/apollographql/execution/federation/coercings.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.apollographql.execution.federation | ||
|
||
import com.apollographql.apollo.ast.GQLBooleanValue | ||
import com.apollographql.apollo.ast.GQLEnumValue | ||
import com.apollographql.apollo.ast.GQLFloatValue | ||
import com.apollographql.apollo.ast.GQLIntValue | ||
import com.apollographql.apollo.ast.GQLListValue | ||
import com.apollographql.apollo.ast.GQLNullValue | ||
import com.apollographql.apollo.ast.GQLObjectValue | ||
import com.apollographql.apollo.ast.GQLStringValue | ||
import com.apollographql.apollo.ast.GQLValue | ||
import com.apollographql.apollo.ast.GQLVariableValue | ||
import com.apollographql.execution.Coercing | ||
import com.apollographql.execution.JsonValue | ||
|
||
object _AnyCoercing: Coercing<Any?> { | ||
override fun serialize(internalValue: Any?): JsonValue { | ||
return internalValue | ||
} | ||
|
||
override fun deserialize(value: JsonValue): Any? { | ||
return value | ||
} | ||
|
||
override fun parseLiteral(value: GQLValue): Any? { | ||
return when (value) { | ||
is GQLBooleanValue -> value.value | ||
is GQLEnumValue -> value.value | ||
is GQLFloatValue -> value.value | ||
is GQLIntValue -> value.value | ||
is GQLListValue -> value.values.map { parseLiteral(it) } | ||
is GQLNullValue -> null | ||
is GQLObjectValue -> value.fields.map { it.name to parseLiteral(it.value) }.toMap() | ||
is GQLStringValue -> value.value | ||
is GQLVariableValue -> error("Cannot coerce variable") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.