diff --git a/HelpTOC.json b/HelpTOC.json index 2d378ea..69b2cd7 100644 --- a/HelpTOC.json +++ b/HelpTOC.json @@ -1 +1 @@ -{"entities":{"pages":{"-7a6n2h_2":{"id":"-7a6n2h_2","title":"GitHub","url":"https://github.com/apollographql/apollo-kotlin-execution","level":0,"tabIndex":0},"-7a6n2h_3":{"id":"-7a6n2h_3","title":"Kdoc","url":"https://apollographql.github.io/apollo-kotlin-execution/kdoc","level":0,"tabIndex":1},"-7a6n2h_4":{"id":"-7a6n2h_4","title":"Welcome","level":0,"pages":["getting-started","schema","scalars","execution-context","persisted-documents","ide","schema-dump"],"tabIndex":2},"getting-started":{"id":"getting-started","title":"Getting started","url":"getting-started.html","level":1,"parentId":"-7a6n2h_4","tabIndex":0},"schema":{"id":"schema","title":"Generating a schema","url":"schema.html","level":1,"parentId":"-7a6n2h_4","tabIndex":1},"scalars":{"id":"scalars","title":"Custom scalars","url":"scalars.html","level":1,"parentId":"-7a6n2h_4","tabIndex":2},"execution-context":{"id":"execution-context","title":"Execution context","url":"execution-context.html","level":1,"parentId":"-7a6n2h_4","tabIndex":3},"persisted-documents":{"id":"persisted-documents","title":"Persisted documents","url":"persisted-documents.html","level":1,"parentId":"-7a6n2h_4","tabIndex":4},"ide":{"id":"ide","title":"IDE","url":"ide.html","level":1,"parentId":"-7a6n2h_4","tabIndex":5},"schema-dump":{"id":"schema-dump","title":"Monitoring the generated schema","url":"schema-dump.html","level":1,"parentId":"-7a6n2h_4","tabIndex":6},"-7a6n2h_5":{"id":"-7a6n2h_5","title":"Integrations","level":0,"pages":["ktor","http4k","spring"],"tabIndex":3},"ktor":{"id":"ktor","title":"Ktor","url":"ktor.html","level":1,"parentId":"-7a6n2h_5","tabIndex":0},"http4k":{"id":"http4k","title":"http4k","url":"http4k.html","level":1,"parentId":"-7a6n2h_5","tabIndex":1},"spring":{"id":"spring","title":"Spring","url":"spring.html","level":1,"parentId":"-7a6n2h_5","tabIndex":2},"-7a6n2h_6":{"id":"-7a6n2h_6","title":"Apollo Federation","level":0,"pages":["federation"],"tabIndex":4},"federation":{"id":"federation","title":"Apollo Federation","url":"federation.html","level":1,"parentId":"-7a6n2h_6","tabIndex":0},"-7a6n2h_7":{"id":"-7a6n2h_7","title":"Apollo Usage Reporting","level":0,"pages":["usage-reporting"],"tabIndex":5},"usage-reporting":{"id":"usage-reporting","title":"Apollo Usage Reporting","url":"usage-reporting.html","level":1,"parentId":"-7a6n2h_7","tabIndex":0}}},"topLevelIds":["-7a6n2h_2","-7a6n2h_3","-7a6n2h_4","-7a6n2h_5","-7a6n2h_6","-7a6n2h_7"]} \ No newline at end of file +{"entities":{"pages":{"oregoy_2":{"id":"oregoy_2","title":"GitHub","url":"https://github.com/apollographql/apollo-kotlin-execution","level":0,"tabIndex":0},"oregoy_3":{"id":"oregoy_3","title":"Kdoc","url":"https://apollographql.github.io/apollo-kotlin-execution/kdoc","level":0,"tabIndex":1},"oregoy_4":{"id":"oregoy_4","title":"Welcome","level":0,"pages":["getting-started","schema","scalars","execution-context","persisted-documents","ide","schema-dump"],"tabIndex":2},"getting-started":{"id":"getting-started","title":"Getting started","url":"getting-started.html","level":1,"parentId":"oregoy_4","tabIndex":0},"schema":{"id":"schema","title":"Generating a schema","url":"schema.html","level":1,"parentId":"oregoy_4","tabIndex":1},"scalars":{"id":"scalars","title":"Custom scalars","url":"scalars.html","level":1,"parentId":"oregoy_4","tabIndex":2},"execution-context":{"id":"execution-context","title":"Execution context","url":"execution-context.html","level":1,"parentId":"oregoy_4","tabIndex":3},"persisted-documents":{"id":"persisted-documents","title":"Persisted documents","url":"persisted-documents.html","level":1,"parentId":"oregoy_4","tabIndex":4},"ide":{"id":"ide","title":"IDE","url":"ide.html","level":1,"parentId":"oregoy_4","tabIndex":5},"schema-dump":{"id":"schema-dump","title":"Monitoring the generated schema","url":"schema-dump.html","level":1,"parentId":"oregoy_4","tabIndex":6},"oregoy_5":{"id":"oregoy_5","title":"Integrations","level":0,"pages":["ktor","http4k","spring"],"tabIndex":3},"ktor":{"id":"ktor","title":"Ktor","url":"ktor.html","level":1,"parentId":"oregoy_5","tabIndex":0},"http4k":{"id":"http4k","title":"http4k","url":"http4k.html","level":1,"parentId":"oregoy_5","tabIndex":1},"spring":{"id":"spring","title":"Spring","url":"spring.html","level":1,"parentId":"oregoy_5","tabIndex":2},"oregoy_6":{"id":"oregoy_6","title":"Apollo Federation","level":0,"pages":["federation"],"tabIndex":4},"federation":{"id":"federation","title":"Apollo Federation","url":"federation.html","level":1,"parentId":"oregoy_6","tabIndex":0},"oregoy_7":{"id":"oregoy_7","title":"Apollo Usage Reporting","level":0,"pages":["usage-reporting"],"tabIndex":5},"usage-reporting":{"id":"usage-reporting","title":"Apollo Usage Reporting","url":"usage-reporting.html","level":1,"parentId":"oregoy_7","tabIndex":0}}},"topLevelIds":["oregoy_2","oregoy_3","oregoy_4","oregoy_5","oregoy_6","oregoy_7"]} \ No newline at end of file diff --git a/execution-context.html b/execution-context.html index 471a5a6..3cbcc36 100644 --- a/execution-context.html +++ b/execution-context.html @@ -1,5 +1,5 @@ -Execution context | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Execution context

Kotlin functions may define an additional ExecutionContext parameter. This parameter is special and never exposed in GraphQL.

Kotlin

GraphQL

+}

Apollo Kotlin Execution Help

Execution context

Kotlin functions may define an additional ExecutionContext parameter. This parameter is special and never exposed in GraphQL.

Kotlin

GraphQL

@GraphQLQuery class Query { fun viewer(context: ExecutionContext): User { @@ -21,19 +21,19 @@ return user } } -
+
type Query { # this field has no arguments viewer: user } -

ExecutionContext is a typesafe map inspired by CoroutinesContext. Define your own context by extending ExecutionContext.Element:

+

ExecutionContext is a typesafe map inspired by CoroutinesContext. Define your own context by extending ExecutionContext.Element:

class CurrentUser(val id: String) : ExecutionContext.Element { override val key: ExecutionContext.Key<*> get() = Key companion object Key : ExecutionContext.Key<CurrentUser> } -

And pass it to ExecutableSchema.execute():

+

And pass it to ExecutableSchema.execute():

// Get the current logged-in user val context = CurrentUser(getUserIdFromHttpHeaders()) @@ -43,7 +43,7 @@ .build(), context ) -

CurrentUser is now available in Query.viewer:

+

CurrentUser is now available in Query.viewer:

class Query { fun viewer(context: ExecutionContext): User { val id = context[CurrentUser]!!.id diff --git a/federation.html b/federation.html index f055e6d..0f7d989 100644 --- a/federation.html +++ b/federation.html @@ -1,5 +1,5 @@ -Apollo Federation | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Apollo Federation

Apollo Kotlin Execution supports Apollo Federation.

To use federation, add the apollo-execution-subgraph artifact to your project:

+}

Apollo Kotlin Execution Help

Apollo Federation

Apollo Kotlin Execution supports Apollo Federation.

To use federation, add the apollo-execution-subgraph artifact to your project:

dependencies { // Add the federation dependency implementation("com.apollographql.execution:apollo-execution-subgraph:0.1.0") } -

The apollo-execution-subgraph artifact contains the @GraphQLKey annotation allowing you to define entities.

Defining entities

You can define an entity key using the @GraphQLKey annotation:

+

The apollo-execution-subgraph artifact contains the @GraphQLKey annotation allowing you to define entities.

Defining entities

You can define an entity key using the @GraphQLKey annotation:

class Product( @GraphQLKey val id: String, val name: String ) -

The @GraphQLKey annotation is translated at build time into a matching federation @key directive:

+

The @GraphQLKey annotation is translated at build time into a matching federation @key directive:

@key(fields: "id") type Product { id: String!, name: String! } -

Auto-generated meta fields

Whenever a type containing a @GraphQLKey field is present, Apollo Kotlin Execution adds the federation subgraph fields, _service and _entities:

+

Auto-generated meta fields

Whenever a type containing a @GraphQLKey field is present, Apollo Kotlin Execution adds the federation subgraph fields, _service and _entities:

# 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. @@ -44,7 +44,7 @@ _entities(representations: [_Any!]!): [_Entity]! _service: _Service! } -

Defining entity resolvers

In order to support the _entities field, federation requires a resolver that can resolve an entity from its key fields.

You can add one by defining a resolve function on the companion object:

+

Defining entity resolvers

In order to support the _entities field, federation requires a resolver that can resolve an entity from its key fields.

You can add one by defining a resolve function on the companion object:

class Product( @GraphQLKey val id: String, @@ -61,7 +61,7 @@ Product("1", "foo"), Product("2", "bar") ) -

Just like regular resolvers, the entity resolvers can be suspend and/or have an ExecutionContext parameter:

+

Just like regular resolvers, the entity resolvers can be suspend and/or have an ExecutionContext parameter:

class Product( @GraphQLKey val id: String, @@ -73,7 +73,7 @@ } } } -

Tracing (ftv1)

Apollo Kotlin Execution supports federated tracing (ftv1).

Ftv1 records timing information for each field and reports that information to the router through the "ftv1" extension.

To enable federated tracing, configure your ExecutableSchema with a Ftv1Instrumentation and matching Ftv1Context:

+

Tracing (ftv1)

Apollo Kotlin Execution supports federated tracing (ftv1).

Ftv1 records timing information for each field and reports that information to the router through the "ftv1" extension.

To enable federated tracing, configure your ExecutableSchema with a Ftv1Instrumentation and matching Ftv1Context:

// Install the Ftv1Instrumentation in the executable schema val schema = ServiceExecutableSchemaBuilder() .addInstrumentation(Ftv1Instrumentation()) @@ -85,7 +85,7 @@ // The information is a Base64 encoded protobuf message used by the router val ftv1 = response.extensions.get("ftv1") -

Sending the "ftv1" extension has some overhead and in real life scenarios, the router uses sampling to save network bandwidth.

This is done using the "apollo-federation-include-trace" HTTP header:

+

Sending the "ftv1" extension has some overhead and in real life scenarios, the router uses sampling to save network bandwidth.

This is done using the "apollo-federation-include-trace" HTTP header:

val ftv1Context = if (httpHeaders.get("apollo-federation-include-trace") == "ftv1") { // The router required tracing information for this request Ftv1Context() diff --git a/getting-started.html b/getting-started.html index 3195fa0..e2c8295 100644 --- a/getting-started.html +++ b/getting-started.html @@ -1,5 +1,5 @@ -Getting started | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Getting started

Apollo Kotlin Execution is a code-first GraphQL execution library.

Apollo Kotlin Execution:

  • Generates a GraphQL schema from your Kotlin code: write Kotlin, get a typesafe API.

  • Doesn't use reflection. Use it on the JVM and enjoy ultra-fast start times. Or use it with Kotlin native. Apollo Kotlin Execution is KMP-ready!

  • Supports custom scalars, subscriptions, persisted queries and everything in the current GraphQL draft.

  • Integrates with Ktor, http4k and Spring.

  • Supports Apollo Federation.

Under the hood, Apollo Kotlin Execution uses KSP to generate GraphQL resolvers and types from your Kotlin code.

Gradle configuration

Apollo Kotlin Execution comes with a Gradle plugin that:

  • Configures KSP:

    • Adds apollo-execution-processor to the KSP configuration.

    • Configure service & packageName KSP arguments.

  • Configures dependency resolution to align Apollo Kotlin Execution versions if none is specified.

  • Adds apolloCheckSchema and apolloDumpSchema tasks (see Monitoring the generated schema)

Configure your Gradle build:

+}

Apollo Kotlin Execution Help

Getting started

Apollo Kotlin Execution is a code-first GraphQL execution library.

Apollo Kotlin Execution:

  • Generates a GraphQL schema from your Kotlin code: write Kotlin, get a typesafe API.

  • Doesn't use reflection. Use it on the JVM and enjoy ultra-fast start times. Or use it with Kotlin native. Apollo Kotlin Execution is KMP-ready!

  • Supports custom scalars, subscriptions, persisted queries and everything in the current GraphQL draft.

  • Integrates with Ktor, http4k and Spring.

  • Supports Apollo Federation.

Under the hood, Apollo Kotlin Execution uses KSP to generate GraphQL resolvers and types from your Kotlin code.

Gradle configuration

Apollo Kotlin Execution comes with a Gradle plugin that:

  • Configures KSP:

    • Adds apollo-execution-processor to the KSP configuration.

    • Configure service & packageName KSP arguments.

  • Configures dependency resolution to align Apollo Kotlin Execution versions if none is specified.

  • Adds apolloCheckSchema and apolloDumpSchema tasks (see Monitoring the generated schema)

Configure your Gradle build:

// build.gradle.kts plugins { // Kotlin and KSP are required @@ -34,7 +34,7 @@ packageName = "com.example" } } -

Define your root query

Write your root query class in a Query.kt file:

+

Define your root query

Write your root query class in a Query.kt file:

// @GraphQLQuery is the entry point for KSP processing @GraphQLQuery class Query { @@ -48,18 +48,18 @@ return "Hello $name" } } -

Run the codegen:

+

Run the codegen:

./gradlew kspKotlin # or if multiplatform ./gradlew kspCommonMainKotlinMetadata -

Execute your query

The codegen generates a com.example.ServiceExecutableSchemaBuilder class that is the entry point to execute GraphQL requests:

+

Execute your query

The codegen generates a com.example.ServiceExecutableSchemaBuilder class that is the entry point to execute GraphQL requests:

val executableSchema = ServiceExecutableSchemaBuilder() .build() -

Create a GraphQL request:

+

Create a GraphQL request:

val request = GraphQLRequest.Builder() .document("{ hello(name: \"sample\") }") .build() -

Execute the GraphQL request:

+

Execute the GraphQL request:

val response = executableSchema.execute( request, ExecutionContext.Empty @@ -67,4 +67,4 @@ println(response.data) // {hello=Hello sample} -

Apollo Kotlin Execution supports objects, interfaces, unions, enum, input objects, deprecation, customizing names and descriptions and more.

See the Generating a schema page for more details.

Integrate with your favorite server library

Apollo Kotlin Execution comes with integrations for popular server libraries:

See the respective documentation for how to configure a server with an ExecutableSchema.

Last modified: 31 October 2024
\ No newline at end of file +

Apollo Kotlin Execution supports objects, interfaces, unions, enum, input objects, deprecation, customizing names and descriptions and more.

See the Generating a schema page for more details.

Integrate with your favorite server library

Apollo Kotlin Execution comes with integrations for popular server libraries:

See the respective documentation for how to configure a server with an ExecutableSchema.

Last modified: 31 October 2024
\ No newline at end of file diff --git a/http4k.html b/http4k.html index 2b92047..1034e6a 100644 --- a/http4k.html +++ b/http4k.html @@ -1,5 +1,5 @@ -http4k | Apollo Kotlin Execution

Apollo Kotlin Execution Help

http4k

To use the http4k integration, add apollo-execution-http4k to your dependencies and the http4k bom:

+}

Apollo Kotlin Execution Help

http4k

To use the http4k integration, add apollo-execution-http4k to your dependencies and the http4k bom:

dependencies { // Add the runtime dependency implementation("com.apollographql.execution:apollo-execution-http4k:0.1.0") @@ -24,10 +24,10 @@ // See https://www.http4k.org/guide/reference/servers/ implementation("org.http4k:http4k-server-netty") } -

apollo-execution-ktor provides an apolloHandler(ExecutableSchema) function that handles the /graphql route:

+

apollo-execution-ktor provides an apolloHandler(ExecutableSchema) function that handles the /graphql route:

val executableSchema = ServiceExecutableSchemaBuilder().build() apolloHandler(executableSchema) .asServer(Netty(8000)) .start() .block() -
Last modified: 29 August 2024
\ No newline at end of file +
Last modified: 29 August 2024
\ No newline at end of file diff --git a/ide.html b/ide.html index e4a84bb..e2e9fe0 100644 --- a/ide.html +++ b/ide.html @@ -1,5 +1,5 @@ -IDE | Apollo Kotlin Execution

Apollo Kotlin Execution Help

IDE

One of GraphQL strong points is tooling.

Apollo Kotlin Execution comes with a built-in IDE that makes it easy to explore your schema and debug your operations.

You can get a ready-to-serve version of Apollo Sandbox using the sandboxHtml() function:

+}

Apollo Kotlin Execution Help

IDE

Apollo Kotlin Execution comes with a built-in IDE that makes it easy to explore your schema, write your operation with autocomplete and execute them.

You can get a ready-to-serve version of Apollo Sandbox using the sandboxHtml() function:

val pageTitle = "Welcome to my API" val initialEndpoint = "http://localhost:8080/graphql" -sandboxHtml(title = pageTitle, initialEndpoint = initialEndpoint) -

Apollo Sandbox

You can then serve it using your favorite server or use any of the existing integrations:

Last modified: 08 November 2024
\ No newline at end of file +val html = sandboxHtml(title = pageTitle, initialEndpoint = initialEndpoint) + +// Expose this graphql to your route of choice, /sandbox for an example +get("/sandbox") { + respondHtml(html) +} +

Apollo Sandbox

The builtin integrations provide helper functions for this:

Last modified: 08 November 2024
\ No newline at end of file diff --git a/ktor.html b/ktor.html index 80e89d6..a38c70d 100644 --- a/ktor.html +++ b/ktor.html @@ -1,5 +1,5 @@ -Ktor | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Ktor

To use the Ktor integration, add apollo-execution-ktor to your dependencies and a Ktor engine:

+}

Apollo Kotlin Execution Help

Ktor

To use the Ktor integration, add apollo-execution-ktor to your dependencies and a Ktor engine:

dependencies { // Add the runtime dependency implementation("com.apollographql.execution:apollo-execution-ktor:0.1.0") @@ -21,14 +21,14 @@ // See https://ktor.io/ for other choices. implementation("io.ktor:ktor-server-netty:3.0.0") } -

apollo-execution-ktor provides an apolloModule(ExecutableSchema) function that adds a /graphql route to your application:

+

apollo-execution-ktor provides an apolloModule(ExecutableSchema) function that adds a /graphql route to your application:

embeddedServer(Netty, port = 8080) { // /graphql route apolloModule(ServiceExecutableSchemaBuilder().build()) }.start(wait = true) -

You can also opt in the Apollo Sandbox route by using apolloSandboxModule()

+

You can also opt in the Apollo Sandbox route by using apolloSandboxModule()

embeddedServer(Netty, port = 8080) { // /sandbox/index.html route apolloSandboxModule() } -

apolloSandboxModule() adds a sandbox/index.html route to your application.

Open http://localhost:8080/sandbox/index.html and try out your API in the Apollo sandbox

Apollo Sandbox

Last modified: 21 October 2024
\ No newline at end of file +

apolloSandboxModule() adds a sandbox/index.html route to your application.

Open http://localhost:8080/sandbox/index.html and try out your API in the Apollo sandbox

Apollo Sandbox

Last modified: 21 October 2024
\ No newline at end of file diff --git a/persisted-documents.html b/persisted-documents.html index 7da8b9e..38a6022 100644 --- a/persisted-documents.html +++ b/persisted-documents.html @@ -1,5 +1,5 @@ -Persisted documents | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Persisted documents

Automatic persisted documents

Apollo Kotlin Execution supports Automatic Persisted Queries.

To enable them, call persistedDocumentCache():

+}

Apollo Kotlin Execution Help

Persisted documents

Automatic persisted documents

Apollo Kotlin Execution supports Automatic Persisted Queries.

To enable them, call persistedDocumentCache():

val executableSchema = ServiceExecutableSchemaBuilder() .persistedDocumentCache(InMemoryPersistedDocumentCache()) .build() diff --git a/scalars.html b/scalars.html index b32ebf1..79ada53 100644 --- a/scalars.html +++ b/scalars.html @@ -1,5 +1,5 @@ -Custom scalars | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Custom scalars

You can define a new custom scalar using @GraphQLScalar:

Kotlin

GraphQL

+}

Apollo Kotlin Execution Help

Custom scalars

You can define a new custom scalar using @GraphQLScalar:

Kotlin

GraphQL

@GraphQLScalar(GeoPointCoercing::class) class GeoPoint( val latitude: Double, val longitude: Double ) -
+
scalar GeoPoint -

@GraphQLScalar can also be added to typealiases for the times when you don't own the target class:

Kotlin

GraphQL

+

@GraphQLScalar can also be added to typealiases for the times when you don't own the target class:

Kotlin

GraphQL

import kotlinx.datetime.LocalDateTime @GraphQLScalar(DateTimeCoercing::class) typealias DateTime = LocalDateTime -
+
scalar DateTime -

Implementing the Coercing interface

Each custom scalar requires a matching Coercing implementation:

+

Implementing the Coercing interface

Each custom scalar requires a matching Coercing implementation:

interface Coercing<T> { /** * Serializes from an internal value (Kotlin) to an external value (typically JSON). @@ -48,22 +48,22 @@ */ fun parseLiteral(gqlValue: GQLValue): T } -

serialize is needed if your scalar is used in an output position:

+

serialize is needed if your scalar is used in an output position:

type User { # serialize() is called here to serialize a `GeoPoint` to JSON $position: GeoPoint } -

deserialize is needed if your scalar is used in a variable:

+

deserialize is needed if your scalar is used in a variable:

query GetUser($position: GeoPoint) { # Get all users in a 100m range from the given position usersByPosition(position: $position, radius: 100.0) {} } -

parseLiteral is needed if your scalar is used as a GraphQL literal:

+

parseLiteral is needed if your scalar is used as a GraphQL literal:

query GetUserInParis { # Get all users in a 1km range from the center of Paris usersByPosition(position: { latitude: 48.8588475, longitude: 2.3058358}, radius: 1000.0) {} } -

With the above, a possible implementation for GeoPointCoercing is:

+

With the above, a possible implementation for GeoPointCoercing is:

@GraphQLCoercing class GeoPointCoercing: Coercing<GeoPoint> { override fun serialize(internalValue: GeoPoint): ExternalValue { @@ -115,10 +115,10 @@ ) } } -

Built-in Coercings

Apollo Kotlin Execution comes with built-in Coercing for built-in types that you can reuse:

  • StringCoercing

  • IntCoercing

  • FloatCoercing

  • BooleanCoercing

The ID scalar

Despite being a built-in GraphQL scalar, there is no ID type in Kotlin. If you want to use ID in your schema, you need to define the mapping manually.

Typically, ID is mapped either to Int or String.

Mapping ID to String:

+

Built-in Coercings

Apollo Kotlin Execution comes with built-in Coercing for built-in types that you can reuse:

  • StringCoercing

  • IntCoercing

  • FloatCoercing

  • BooleanCoercing

The ID scalar

Despite being a built-in GraphQL scalar, there is no ID type in Kotlin. If you want to use ID in your schema, you need to define the mapping manually.

Typically, ID is mapped either to Int or String.

Mapping ID to String:

@GraphQLScalar(StringCoercing) typealias ID = String -

Mapping ID to Int:

+

Mapping ID to Int:

@GraphQLScalar(IntCoercing) typealias ID = Int
Last modified: 16 July 2024
\ No newline at end of file diff --git a/schema-dump.html b/schema-dump.html index 6c51fab..3fe4108 100644 --- a/schema-dump.html +++ b/schema-dump.html @@ -1,5 +1,5 @@ -Monitoring the generated schema | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Monitoring the generated schema

When working with Kotlin code, it's easy to introduce unwanted changes to your GraphQL schema. Not every Kotlin construct needs to be part of your exported GraphQL API.

For this reason, Apollo Kotlin Execution comes with built-in monitoring of your GraphQL schema. The Gradle plugin adds an apolloCheckSchema task that is run automatically whenever you run ./gradlew check (and therefore ./gradlew build).

For an example, if you add a exposedByMistake() function, running ./gradlew apolloCheckSchema fails with the below:

+}

Apollo Kotlin Execution Help

Monitoring the generated schema

When working with Kotlin code, it's easy to introduce unwanted changes to your GraphQL schema. Not every Kotlin construct needs to be part of your exported GraphQL API.

For this reason, Apollo Kotlin Execution comes with built-in monitoring of your GraphQL schema. The Gradle plugin adds an apolloCheckSchema task that is run automatically whenever you run ./gradlew check (and therefore ./gradlew build).

For an example, if you add a exposedByMistake() function, running ./gradlew apolloCheckSchema fails with the below:

$ ./gradlew apolloCheckSchema > Task :apolloCheckSchema FAILED @@ -34,7 +34,7 @@ Run 'apolloDumpSchema' to overwrite the schema. -

If the change is unwanted, then you can fix your code to hide it.

If the change is in fact desired, you can run ./gradlew apolloDumpSchema and commit the resulted file to make the check pass:

+

If the change is unwanted, then you can fix your code to hide it.

If the change is in fact desired, you can run ./gradlew apolloDumpSchema and commit the resulted file to make the check pass:

$ ./gradlew apolloDumpSchema BUILD SUCCESSFUL in 522ms $ git diff graphql/ diff --git a/schema.html b/schema.html index 92c1ae8..897a076 100644 --- a/schema.html +++ b/schema.html @@ -1,5 +1,5 @@ -Generating a schema | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Generating a schema

Apollo Kotlin Execution uses KSP to parse your Kotlin code and generate a matching GraphQL schema.

To identify a graph, the Kotlin code must contain exactly one @GraphQLQuery class and at most one optional @GraphQLMutation and @GraphQLSubscription classes:

+}

Apollo Kotlin Execution Help

Generating a schema

Apollo Kotlin Execution uses KSP to parse your Kotlin code and generate a matching GraphQL schema.

To identify a graph, the Kotlin code must contain exactly one @GraphQLQuery class and at most one optional @GraphQLMutation and @GraphQLSubscription classes:

// Mandatory top-level Query @GraphQLQuery class Query { @@ -28,39 +28,39 @@ // Optional top-level Subscription @GraphQLSubscription class Subscription { } -

From those root classes, the Apollo Kotlin Execution processor traverses the Kotlin class graph and builds the matching GraphQL schema:

  • Classes used in output positions are mapped to objects, unions and interfaces.

  • Classes used in input positions are mapped to input objects.

  • Scalars and Enum can happen in both input and output position.

Whenever possible, the order of fields in the generated GraphQL schema is the same as the declaration order in Kotlin.

Objects and fields

Apollo Kotlin Execution maps public Kotlin classes to GraphQL types and public functions and properties to GraphQL fields with the same name:

Kotlin

GraphQL

+

From those root classes, the Apollo Kotlin Execution processor traverses the Kotlin class graph and builds the matching GraphQL schema:

  • Classes used in output positions are mapped to objects, unions and interfaces.

  • Classes used in input positions are mapped to input objects.

  • Scalars and Enum can happen in both input and output position.

Whenever possible, the order of fields in the generated GraphQL schema is the same as the declaration order in Kotlin.

Objects and fields

Apollo Kotlin Execution maps public Kotlin classes to GraphQL types and public functions and properties to GraphQL fields with the same name:

Kotlin

GraphQL

class User(val id: String) { fun email(): String } -
+
type User { id: String! email: String! } -

Private/internal fields and functions are not exposed in GraphQL:

Kotlin

GraphQL

+

Private/internal fields and functions are not exposed in GraphQL:

Kotlin

GraphQL

class User { fun email(): String internal fun sendVerificationEmail() } -
+
type User { email: String! } -

Unions and interfaces

Non-empty Kotlin interfaces are mapped to GraphQL interfaces:

Kotlin

GraphQL

+

Unions and interfaces

Non-empty Kotlin interfaces are mapped to GraphQL interfaces:

Kotlin

GraphQL

sealed interface Node { id: String } class User( override val id: String ) : Node -
+
interface Node { id: String! } type User implements Node { id: String! } -

Empty Kotlin interfaces are mapped to GraphQL unions:

Kotlin

GraphQL

+

Empty Kotlin interfaces are mapped to GraphQL unions:

Kotlin

GraphQL

sealed interface Actor class User( val id: String, @@ -69,7 +69,7 @@ class Organisation( val users: List<User> ) : Actor -
+
union Actor = User | Organisation type User { val id: String! @@ -78,47 +78,47 @@ type Organisation { val users: [User] } -

Enums

Kotlin enums are mapped to GraphQL enums:

Kotlin

GraphQL

+

Enums

Kotlin enums are mapped to GraphQL enums:

Kotlin

GraphQL

enum class Role { Read, Write, Admin } -
+
enum Role { Read, Write, Admin } -

Scalars

Classes annotated with @GraphQLScalar are mapped to GraphQL scalars:

Kotlin

GraphQL

+

Scalars

Classes annotated with @GraphQLScalar are mapped to GraphQL scalars:

Kotlin

GraphQL

@GraphQLScalar(GeoPointCoercing::class) class GeoPoint( val latitude: Double, val longitude: Double ) -
+
scalar GeoPoint -

You can also map existing classes that you don't own to GraphQL scalars using typealias

Kotlin

GraphQL

+

You can also map existing classes that you don't own to GraphQL scalars using typealias

Kotlin

GraphQL

import kotlinx.datetime.LocalDateTime @GraphQLScalar(DateTimeCoercing::class) typealias DateTime = LocalDateTime -
+
scalar DateTime -

Arguments

Kotlin parameters are mapped to GraphQL arguments:

Kotlin

GraphQL

+

Arguments

Kotlin parameters are mapped to GraphQL arguments:

Kotlin

GraphQL

class Organisation { fun users( first: Int, after: String ): UserConnection } -
+
type Organisation { users( first: Int!, after: String! ): UserConnection! } -

Use Optional<> anf @GraphQLDefault to further control your input values.

Note that because nullability vs optionality are so closely related in GraphQL, not all combination are allowed:

+

Use Optional<> anf @GraphQLDefault to further control your input values.

Note that because nullability vs optionality are so closely related in GraphQL, not all combination are allowed:

type Query { // A non-null argument fun fieldA(arg: Int) = 0 @@ -144,7 +144,7 @@ // Disallowed: there is a default value and the argument type cannot be optional //fun fieldH(@GraphQLDefault("10") arg: Optional<Int>) = 0 } -

Kotlin parameters may be of class type in which case the class is generated as a GraphQL input object:

Kotlin

GraphQL

+

Kotlin parameters may be of class type in which case the class is generated as a GraphQL input object:

Kotlin

GraphQL

class UserFilter( val role: Role?, val organisationId: String? @@ -154,7 +154,7 @@ where: UserFilter, ): List<User> } -
+
input UserFilter { role: Role, organisationId: String @@ -164,17 +164,17 @@ where: UserFilter!, ): [User!] } -

Names

The GraphQL name can be customized using @GraphQLName:

Kotlin

GraphQL

+

Names

The GraphQL name can be customized using @GraphQLName:

Kotlin

GraphQL

@GraphQLName("User") class DomainUser { @GraphQLName("email") fun emailAddress(): String } -
+
type User { email: String } -

Descriptions

The GraphQL description is generated from the KDoc:

Kotlin

GraphQL

+

Descriptions

The GraphQL description is generated from the KDoc:

Kotlin

GraphQL

/** * A logged-in user of the service. */ @@ -184,7 +184,7 @@ */ fun email(): String } -
+
""" A logged-in user of the service. """ @@ -194,39 +194,39 @@ """ email: String } -

Nullability

Nullable fields and input fields are also nullable in GraphQL:

Kotlin

GraphQL

+

Nullability

Nullable fields and input fields are also nullable in GraphQL:

Kotlin

GraphQL

class User { fun email(): String? fun id(): String } -
+
type User { email: String id: String! } -

Directives

Define custom directives using @GraphQLDirective:

Kotlin

GraphQL

+

Directives

Define custom directives using @GraphQLDirective:

Kotlin

GraphQL

/** * A field requires a specific opt-in */ @GraphQLDirective annotation class requiresOptIn(val feature: String) -
+
""" A field requires a specific opt-in """ directive @requiresOptIn(feature: String!) on FIELD_DEFINITION -

Use your directive by annotating your Kotlin code:

Kotlin

GraphQL

+

Use your directive by annotating your Kotlin code:

Kotlin

GraphQL

class Query { @requiresOptIn(feature = "experimental") fun experimentalField(): String { TODO() } } -
+
type Query { experimentalField: String! @requiresOptIn(feature: "experimental") } -

The order of the directives in the GraphQL schema is the same as the order of the annotations in the Kotlin code.

Kotlin annotation classes are mapped to input objects when used as parameter types:

Kotlin

GraphQL

+

The order of the directives in the GraphQL schema is the same as the order of the annotations in the Kotlin code.

Kotlin annotation classes are mapped to input objects when used as parameter types:

Kotlin

GraphQL

enum class OptInLevel { Ignore, Warning, @@ -238,7 +238,7 @@ ) @GraphQLDirective annotation class requiresOptIn(val feature: OptInFeature) -
+
enum OptInLevel { Ignore, Warning, @@ -249,28 +249,28 @@ level: OptInLevel! } directive @requiresOptIn(feature: OptInFeature!) on FIELD_DEFINITION -

Limitations:

  1. It is impossible to reuse other input objects in directive arguments. The directive input objects can only be used in directives. This is because Kotlin annotations do not support regular class paramaters, only annotation classes unlike regular function parameters.

  2. Directive arguments cannot have default values. This is because KSP does not support reading Kotlin default values and using @GraphQLDefault only without a default value would not compile.

Deprecation

Kotlin symbols annotated as @Deprecated are marked deprecated in GraphQL when applicable:

Kotlin

GraphQL

+

Limitations:

  1. It is impossible to reuse other input objects in directive arguments. The directive input objects can only be used in directives. This is because Kotlin annotations do not support regular class paramaters, only annotation classes unlike regular function parameters.

  2. Directive arguments cannot have default values. This is because KSP does not support reading Kotlin default values and using @GraphQLDefault only without a default value would not compile.

Deprecation

Kotlin symbols annotated as @Deprecated are marked deprecated in GraphQL when applicable:

Kotlin

GraphQL

class User { fun role(): Role @Deprecated("Check for `role == Admin` instead") fun isAdmin(): Boolean } -
+
type User { isAdmin: String @deprecated("Check for `role == Admin` instead") } -

Default values

KSP cannot read default parameter values.

In order to define a default value for your arguments, use @GraphQLDefault and pass the value encoded as GraphQL:

Kotlin

GraphQL

+

Default values

KSP cannot read default parameter values.

In order to define a default value for your arguments, use @GraphQLDefault and pass the value encoded as GraphQL:

Kotlin

GraphQL

class Organisation { fun users( @GraphQLDefault("100") first: Int, @GraphQLDefault("null") after: String? ): UserConnection } -
+
type Organisation { users( first: Int! = 100, after: String = null ): UserConnection! } -

Built-in types

Kotlin built-in types map to their GraphQL equivalent:

Kotlin

GraphQL

Int

Int

String

String

Double

Float

Boolean

Boolean

List

List

Last modified: 08 November 2024
\ No newline at end of file +

Built-in types

Kotlin built-in types map to their GraphQL equivalent:

Kotlin

GraphQL

Int

Int

String

String

Double

Float

Boolean

Boolean

List

List

Last modified: 08 November 2024
\ No newline at end of file diff --git a/spring.html b/spring.html index 950bd1e..7781d94 100644 --- a/spring.html +++ b/spring.html @@ -1,5 +1,5 @@ -Spring | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Spring

Apollo Kotlin Execution comes with Spring Webflux integration.

To use the Spring Webflux integration, add apollo-execution-spring to your dependencies:

+}

Apollo Kotlin Execution Help

Spring

Apollo Kotlin Execution comes with Spring Webflux integration.

To use the Spring Webflux integration, add apollo-execution-spring to your dependencies:

dependencies { // Add the runtime dependency implementation("com.apollographql.execution:apollo-execution-spring:0.1.0") } -

apollo-execution-spring provides apolloGraphQLRoutes(ExecutableSchema) to add GET and POST /graphql routes to your application:

+

apollo-execution-spring provides apolloGraphQLRoutes(ExecutableSchema) to add GET and POST /graphql routes to your application:

@SpringBootApplication class DefaultApplication { @Bean @@ -26,7 +26,7 @@ apolloGraphQLRoutes(ServiceExecutableSchemaBuilder().build()) } } -

You can also opt in the Apollo Sandbox route by using apolloSandboxRoutes()

+

You can also opt in the Apollo Sandbox route by using apolloSandboxRoutes()

@SpringBootApplication class DefaultApplication { @Bean @@ -37,4 +37,4 @@ apolloSandboxRoutes() } } -

apolloSandboxModule() adds a sandbox/index.html route to your application.

Open http://localhost:8080/sandbox/index.html and try out your API in the Apollo sandbox

Apollo Sandbox

Last modified: 05 September 2024
\ No newline at end of file +

apolloSandboxModule() adds a sandbox/index.html route to your application.

Open http://localhost:8080/sandbox/index.html and try out your API in the Apollo sandbox

Apollo Sandbox

Last modified: 05 September 2024
\ No newline at end of file diff --git a/usage-reporting.html b/usage-reporting.html index edd0b97..91f78e8 100644 --- a/usage-reporting.html +++ b/usage-reporting.html @@ -1,5 +1,5 @@ -Apollo Usage Reporting | Apollo Kotlin Execution

Apollo Kotlin Execution Help

Apollo Usage Reporting

Apollo Kotlin Execution supports sending operation and field reports to GraphOS.

Sending usage reports

Operation and field reports are sent using a protobuf protocol to https://usage-reporting.api.apollographql.com/api/ingress/traces.

Apollo Kotlin collects, encodes and sends those reports using the apollo-execution-reporting artifact:

+}

Apollo Kotlin Execution Help

Apollo Usage Reporting

Apollo Kotlin Execution supports sending operation and field reports to GraphOS.

Sending usage reports

Operation and field reports are sent using a protobuf protocol to https://usage-reporting.api.apollographql.com/api/ingress/traces.

Apollo Kotlin collects, encodes and sends those reports using the apollo-execution-reporting artifact:

dependencies { // Add the Apollo monograph artifact implementation("com.apollographql.execution:apollo-execution-reporting:0.1.0") } -

To enable reports, configure your ExecutableSchema with a ApolloReportsInstrumentation and matching ApolloReportsContext:

+

To enable reports, configure your ExecutableSchema with a ApolloReportsInstrumentation and matching ApolloReportsContext:

// Get your API key from the environment or secret manager val apolloKey = System.getenv("APOLLO_KEY")