diff --git a/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaGeneratorHooks.kt b/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaGeneratorHooks.kt index a86f6a1596..1d2d6bccb0 100644 --- a/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaGeneratorHooks.kt +++ b/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaGeneratorHooks.kt @@ -20,6 +20,7 @@ import com.apollographql.federation.graphqljava.printer.ServiceSDLPrinter.genera import com.apollographql.federation.graphqljava.printer.ServiceSDLPrinter.generateServiceSDLV2 import com.expediagroup.graphql.generator.annotations.GraphQLName import com.expediagroup.graphql.generator.directives.DirectiveMetaInformation +import com.expediagroup.graphql.generator.federation.directives.COMPOSE_DIRECTIVE_TYPE import com.expediagroup.graphql.generator.federation.directives.EXTENDS_DIRECTIVE_TYPE import com.expediagroup.graphql.generator.federation.directives.EXTERNAL_DIRECTIVE_TYPE import com.expediagroup.graphql.generator.federation.directives.FEDERATION_SPEC_URL @@ -88,6 +89,7 @@ open class FederatedSchemaGeneratorHooks( REQUIRES_DIRECTIVE_TYPE ) private val federatedDirectiveV2List: List = listOf( + COMPOSE_DIRECTIVE_TYPE, EXTENDS_DIRECTIVE_TYPE, EXTERNAL_DIRECTIVE_TYPE, INACCESSIBLE_DIRECTIVE_TYPE, @@ -127,6 +129,8 @@ open class FederatedSchemaGeneratorHooks( private fun willGenerateFederatedDirectiveV2(directiveInfo: DirectiveMetaInformation) = if (KEY_DIRECTIVE_NAME == directiveInfo.effectiveName) { KEY_DIRECTIVE_TYPE_V2 + } else if (LINK_DIRECTIVE_NAME == directiveInfo.effectiveName) { + LINK_DIRECTIVE_TYPE } else { super.willGenerateDirective(directiveInfo) } diff --git a/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/directives/ComposeDirective.kt b/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/directives/ComposeDirective.kt new file mode 100644 index 0000000000..0da2647281 --- /dev/null +++ b/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/directives/ComposeDirective.kt @@ -0,0 +1,69 @@ +package com.expediagroup.graphql.generator.federation.directives + +import com.expediagroup.graphql.generator.annotations.GraphQLDirective +import graphql.Scalars +import graphql.introspection.Introspection +import graphql.schema.GraphQLArgument +import graphql.schema.GraphQLNonNull + +/** + * ```graphql + * directive @composeDirective(name: String!) repeatable on SCHEMA + * ``` + * + * By default, Supergraph schema excludes all custom directives. The `@composeDirective` is used to specify custom directives that should be exposed in the Supergraph schema. + * + * Example: + * Given `@custom` directive we can preserve it in the Supergraph schema + * + * ```kotlin + * @GraphQLDirective(name = "custom", locations = [Introspection.DirectiveLocation.FIELD_DEFINITION]) + * annotation class CustomDirective + * + * @ComposeDirective(name = "custom") + * class CustomSchema + * + * class SimpleQuery { + * @CustomDirective + * fun helloWorld(): String = "Hello World" + * } + * ``` + * + * it will generate following schema + * + * ```graphql + * schema @composeDirective(name: "@myDirective") @link(import : ["composeDirective", "extends", "external", "inaccessible", "key", "override", "provides", "requires", "shareable", "tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1") { + * query: Query + * } + * + * directive @custom on FIELD_DEFINITION + * + * type Query { + * helloWorld: String! @custom + * } + * ``` + * + * @see @composeDirective definition + */ +@Repeatable +@GraphQLDirective( + name = COMPOSE_DIRECTIVE_NAME, + description = COMPOSE_DIRECTIVE_DESCRIPTION, + locations = [Introspection.DirectiveLocation.SCHEMA] +) +annotation class ComposeDirective(val name: String) + +internal const val COMPOSE_DIRECTIVE_NAME = "composeDirective" +private const val COMPOSE_DIRECTIVE_DESCRIPTION = "Marks underlying custom directive to be included in the Supergraph schema" + +internal val COMPOSE_DIRECTIVE_TYPE: graphql.schema.GraphQLDirective = graphql.schema.GraphQLDirective.newDirective() + .name(COMPOSE_DIRECTIVE_NAME) + .description(COMPOSE_DIRECTIVE_DESCRIPTION) + .validLocations(Introspection.DirectiveLocation.SCHEMA) + .argument( + GraphQLArgument.newArgument() + .name("name") + .type(GraphQLNonNull.nonNull(Scalars.GraphQLString)) + ) + .repeatable(true) + .build() diff --git a/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/directives/LinkDirective.kt b/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/directives/LinkDirective.kt index 33302fdcc5..841ff99415 100644 --- a/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/directives/LinkDirective.kt +++ b/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/directives/LinkDirective.kt @@ -24,7 +24,7 @@ import graphql.schema.GraphQLList import graphql.schema.GraphQLNonNull const val LINK_SPEC_URL = "https://specs.apollo.dev/link/v1.0/" -const val FEDERATION_SPEC_URL = "https://specs.apollo.dev/federation/v2.0" +const val FEDERATION_SPEC_URL = "https://specs.apollo.dev/federation/v2.1" /** * ```graphql diff --git a/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaV2GeneratorTest.kt b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaV2GeneratorTest.kt index d1af8ac0d0..0601539c21 100644 --- a/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaV2GeneratorTest.kt +++ b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaV2GeneratorTest.kt @@ -30,10 +30,13 @@ class FederatedSchemaV2GeneratorTest { fun `verify can generate federated schema`() { val expectedSchema = """ - schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ + schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } + "Marks underlying custom directive to be included in the Supergraph schema" + directive @composeDirective(name: String!) repeatable on SCHEMA + directive @custom on SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION "Marks the field, argument, input field or enum value as deprecated" diff --git a/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/data/integration/composeDirective/CustomSchema.kt b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/data/integration/composeDirective/CustomSchema.kt new file mode 100644 index 0000000000..ad2aec8e68 --- /dev/null +++ b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/data/integration/composeDirective/CustomSchema.kt @@ -0,0 +1,16 @@ +package com.expediagroup.graphql.generator.federation.data.integration.composeDirective + +import com.expediagroup.graphql.generator.annotations.GraphQLDirective +import com.expediagroup.graphql.generator.federation.directives.ComposeDirective +import graphql.introspection.Introspection + +@ComposeDirective(name = "custom") +class CustomSchema + +@GraphQLDirective(name = "custom", locations = [Introspection.DirectiveLocation.FIELD_DEFINITION]) +annotation class CustomDirective + +class SimpleQuery { + @CustomDirective + fun helloWorld(): String = "Hello World" +} diff --git a/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/execution/ServiceQueryResolverTest.kt b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/execution/ServiceQueryResolverTest.kt index abe0455423..2ddc64c8c8 100644 --- a/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/execution/ServiceQueryResolverTest.kt +++ b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/execution/ServiceQueryResolverTest.kt @@ -86,10 +86,13 @@ scalar CustomScalar""" const val BASE_SERVICE_SDL = """ -schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ +schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } +"Marks underlying custom directive to be included in the Supergraph schema" +directive @composeDirective(name: String!) repeatable on SCHEMA + "Marks target object as extending part of the federated schema" directive @extends on OBJECT | INTERFACE @@ -142,10 +145,13 @@ scalar FieldSet const val FEDERATED_SERVICE_SDL_V2 = """ -schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ +schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } +"Marks underlying custom directive to be included in the Supergraph schema" +directive @composeDirective(name: String!) repeatable on SCHEMA + directive @custom on SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION "Marks target object as extending part of the federated schema" diff --git a/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/validation/integration/ComposeDirectiveIT.kt b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/validation/integration/ComposeDirectiveIT.kt new file mode 100644 index 0000000000..681a1d59e7 --- /dev/null +++ b/generator/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/generator/federation/validation/integration/ComposeDirectiveIT.kt @@ -0,0 +1,52 @@ +package com.expediagroup.graphql.generator.federation.validation.integration + +import com.expediagroup.graphql.generator.TopLevelObject +import com.expediagroup.graphql.generator.extensions.print +import com.expediagroup.graphql.generator.federation.data.integration.composeDirective.CustomSchema +import com.expediagroup.graphql.generator.federation.data.integration.composeDirective.SimpleQuery +import com.expediagroup.graphql.generator.federation.toFederatedSchema +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow + +class ComposeDirectiveIT { + + @Test + fun `verifies applying @composeDirective generates valid schema`() { + assertDoesNotThrow { + val schema = toFederatedSchema( + config = federatedTestConfig("com.expediagroup.graphql.generator.federation.data.integration.composeDirective"), + queries = listOf(TopLevelObject(SimpleQuery())), + schemaObject = TopLevelObject(CustomSchema()) + ) + + val expected = """ + schema @composeDirective(name : "custom") @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ + query: Query + } + + "Marks underlying custom directive to be included in the Supergraph schema" + directive @composeDirective(name: String!) repeatable on SCHEMA + + directive @custom on FIELD_DEFINITION + + "Links definitions within the document to external schemas." + directive @link(import: [String], url: String!) repeatable on SCHEMA + + type Query { + _service: _Service! + helloWorld: String! @custom + } + + type _Service { + sdl: String! + } + """.trimIndent() + val actual = schema.print( + includeDirectivesFilter = { directive -> "link" == directive || "composeDirective" == directive || "custom" == directive }, + includeScalarTypes = false + ).trim() + Assertions.assertEquals(expected, actual) + } + } +} diff --git a/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLGradlePluginIT.kt b/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLGradlePluginIT.kt index 46c7c48f57..5d8fea0936 100755 --- a/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLGradlePluginIT.kt +++ b/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLGradlePluginIT.kt @@ -516,10 +516,13 @@ class GraphQLGradlePluginIT : GraphQLGradlePluginAbstractIT() { val expectedFederatedSchemaWithCustomScalar = """ - schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ + schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } + "Marks underlying custom directive to be included in the Supergraph schema" + directive @composeDirective(name: String!) repeatable on SCHEMA + "Marks the field, argument, input field or enum value as deprecated" directive @deprecated( "The reason for the deprecation" diff --git a/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/tasks/GraphQLGenerateSDLTaskIT.kt b/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/tasks/GraphQLGenerateSDLTaskIT.kt index 0b74636760..198e7c6991 100644 --- a/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/tasks/GraphQLGenerateSDLTaskIT.kt +++ b/plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/tasks/GraphQLGenerateSDLTaskIT.kt @@ -65,10 +65,13 @@ internal val DEFAULT_SCHEMA = internal val FEDERATED_SCHEMA = """ - schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ + schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } + "Marks underlying custom directive to be included in the Supergraph schema" + directive @composeDirective(name: String!) repeatable on SCHEMA + "Marks the field, argument, input field or enum value as deprecated" directive @deprecated( "The reason for the deprecation" diff --git a/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-federated/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt b/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-federated/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt index f441a13774..3221c75ffb 100755 --- a/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-federated/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt +++ b/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-federated/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt @@ -36,10 +36,13 @@ class GenerateSDLMojoTest { assertTrue(schemaFile.exists(), "schema file was generated") val expectedSchema = """ - schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ + schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } + "Marks underlying custom directive to be included in the Supergraph schema" + directive @composeDirective(name: String!) repeatable on SCHEMA + "Marks the field, argument, input field or enum value as deprecated" directive @deprecated( "The reason for the deprecation" diff --git a/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-hooks/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt b/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-hooks/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt index c77c30e873..bcdabc7f53 100755 --- a/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-hooks/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt +++ b/plugins/graphql-kotlin-maven-plugin/src/integration/generate-sdl-hooks/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GenerateSDLMojoTest.kt @@ -36,10 +36,13 @@ class GenerateSDLMojoTest { assertTrue(schemaFile.exists(), "schema file was generated") val expectedSchema = """ - schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ + schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } + "Marks underlying custom directive to be included in the Supergraph schema" + directive @composeDirective(name: String!) repeatable on SCHEMA + "Marks the field, argument, input field or enum value as deprecated" directive @deprecated( "The reason for the deprecation" diff --git a/plugins/schema/graphql-kotlin-sdl-generator/src/integrationTest/kotlin/com/expediagroup/graphql/plugin/schema/GenerateCustomSDLTest.kt b/plugins/schema/graphql-kotlin-sdl-generator/src/integrationTest/kotlin/com/expediagroup/graphql/plugin/schema/GenerateCustomSDLTest.kt index 7fb2ea0913..0682f437b4 100644 --- a/plugins/schema/graphql-kotlin-sdl-generator/src/integrationTest/kotlin/com/expediagroup/graphql/plugin/schema/GenerateCustomSDLTest.kt +++ b/plugins/schema/graphql-kotlin-sdl-generator/src/integrationTest/kotlin/com/expediagroup/graphql/plugin/schema/GenerateCustomSDLTest.kt @@ -25,10 +25,13 @@ class GenerateCustomSDLTest { fun `verify we can generate SDL using custom hooks provider`() { val expectedSchema = """ - schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ + schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } + "Marks underlying custom directive to be included in the Supergraph schema" + directive @composeDirective(name: String!) repeatable on SCHEMA + "Marks the field, argument, input field or enum value as deprecated" directive @deprecated( "The reason for the deprecation" diff --git a/website/docs/schema-generator/federation/apollo-federation.mdx b/website/docs/schema-generator/federation/apollo-federation.mdx index f912c94abc..ebf44bb702 100644 --- a/website/docs/schema-generator/federation/apollo-federation.mdx +++ b/website/docs/schema-generator/federation/apollo-federation.mdx @@ -119,10 +119,11 @@ toFederatedSchema( will generate ```graphql -schema @link(import : ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.0"){ +schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1"){ query: Query } +directive @composeDirective(name: String!) repeatable on SCHEMA directive @extends on OBJECT | INTERFACE directive @external on FIELD_DEFINITION directive @inaccessible on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION diff --git a/website/docs/schema-generator/federation/federated-directives.md b/website/docs/schema-generator/federation/federated-directives.md index 5abeec0ca2..530017629e 100644 --- a/website/docs/schema-generator/federation/federated-directives.md +++ b/website/docs/schema-generator/federation/federated-directives.md @@ -6,6 +6,49 @@ title: Federated Directives For more details, see the [Apollo Federation Specification](https://www.apollographql.com/docs/federation/federation-spec/). +## `@composeDirective` directive + +```graphql +directive @composeDirective(name: String!) repeatable on SCHEMA +``` + +By default, Supergraph schema excludes all custom directives. The `@composeDirective` is used to specify custom directives that should be exposed in the Supergraph schema. + +Example: +Given `@custom` directive we can preserve it in the Supergraph schema + +```kotlin +@GraphQLDirective(name = "custom", locations = [Introspection.DirectiveLocation.FIELD_DEFINITION]) +annotation class CustomDirective + +@ComposeDirective(name = "custom") +class CustomSchema + +class SimpleQuery { + @CustomDirective + fun helloWorld(): String = "Hello World" +} +``` + +it will generate following schema + +```graphql +schema +@composeDirective(name: "@myDirective") +@link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.1") +{ + query: Query +} + +directive @custom on FIELD_DEFINITION + +type Query { + helloWorld: String! @custom +} +``` + +See [@composeDirective definition](https://www.apollographql.com/docs/federation/federated-types/federated-directives/#composedirective) for more information. + ## `@contact` directive ```graphql @@ -251,6 +294,19 @@ External schemas are identified by their `url`, which optionally ends with a nam By default, external types should be namespaced (prefixed with `__`, e.g. `key` directive should be namespaced as `federation__key`) unless they are explicitly imported. `graphql-kotlin` automatically imports ALL federation directives to avoid the need for namespacing. +```kotlin +@LinkDirective(url = "https://myspecs.company.dev/foo/v1.0", imports = ["@foo", "bar"]) +class MySchema +``` + +This will generate following schema: + +```graphql +schema @link(import : ["@foo", "bar"], url : "https://myspecs.company.dev/foo/v1.0") { + query: Query +} +``` + :::danger We currently DO NOT support full `@link` directive capability as it requires support for namespacing and renaming imports. This functionality may be added in the future releases. See [@link specification](https://specs.apollo.dev/link/v1.0) for details.