From b13383bc959b899d2a116b147c3ef6a9d4f6529c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bernd=20St=C3=BCbinger?=
<41049452+stuebingerb@users.noreply.github.com>
Date: Wed, 9 Sep 2026 18:52:46 +0200
Subject: [PATCH] docs: documentation overhaul
### Titles
Some pages had no title, some had it set via meta data, some had it
set as level 1 markdown header. And in the end, everything was anyway
overridden by the title set in `mkdocs.yml`.
This consolidates everything to the level 1 markdown header because
that keeps the title closer to the content, and is also rendered
without mkdocs, e.g. in the IDE preview of a single page.
Explicit titles in the navigation configuration are removed to avoid
duplication.
### Weight
Weight doesn't seem to have an effect with explicit navigation
configuration and was removed.
### Uppercase/lowercase
We consolidate all uses of `ktor/Ktor` to `Ktor` for the official name.
In addition, all headings now use title case.
### Missing Sub Headings
Some pages missed an additional "overview" heading as first item, and
some pages missed sub headings at all. Both have been added for better
structure, and a more consistent table of contents.
### Correct Heading Levels
Some pages had level 1 and level 3 headings and are now using level 1
and level 2 instead for proper hierarchies.
### Latest Maven Version
Adds a small snippet to automatically replace `${KGraphQLVersion}`
with the latest release tag.
### Admonitions
Use admonitions to make experimental warnings more visible.
### Missing Content
Add missing content in a few places.
---
docs/content/Examples/index.md | 4 +-
docs/content/Installation/index.md | 13 +--
docs/content/Plugins/ktor.md | 24 ++---
docs/content/Reference/Type System/enums.md | 9 +-
.../Reference/Type System/input-objects.md | 7 +-
.../Type System/objects-and-interfaces.md | 23 +++--
.../content/Reference/Type System/overview.md | 2 +-
docs/content/Reference/Type System/scalars.md | 8 +-
docs/content/Reference/Type System/unions.md | 91 +++++++++----------
docs/content/Reference/configuration.md | 4 +-
docs/content/Reference/deprecation.md | 4 +-
docs/content/Reference/errorHandling.md | 4 +-
docs/content/Reference/operations.md | 12 +--
docs/content/Reference/resolver.md | 81 +++++++++++++++--
docs/content/Reference/stitching.md | 44 +++++++--
docs/content/Tutorials/ktor.md | 34 ++++---
docs/content/Tutorials/starwars.md | 20 ++--
docs/content/assets/replace_maven_version.js | 21 +++++
docs/mkdocs.yml | 41 +++++----
19 files changed, 295 insertions(+), 151 deletions(-)
create mode 100644 docs/content/assets/replace_maven_version.js
diff --git a/docs/content/Examples/index.md b/docs/content/Examples/index.md
index ce7ba74b..6322dfd6 100644
--- a/docs/content/Examples/index.md
+++ b/docs/content/Examples/index.md
@@ -1,6 +1,8 @@
+# Examples
+
Here you can find some example projects using this library:
-1. Basic example using the ktor
+1. Basic example using the Ktor
plugin: [Official Example](https://github.com/stuebingerb/KGraphQL/tree/main/examples/ktor)
1. Todo app that allows for nested todos and different scopes: [Todo Tree](https://github.com/MattLangsenkamp/TodoTree)
1. An article about pairing Kotlin and GraphQL together using
diff --git a/docs/content/Installation/index.md b/docs/content/Installation/index.md
index 2e6c310e..d6e44d9c 100644
--- a/docs/content/Installation/index.md
+++ b/docs/content/Installation/index.md
@@ -1,7 +1,4 @@
----
-title: Getting Started
-weight: 1
----
+# Installation
[](https://search.maven.org/search?q=g:%22de.stuebingerb%22%20AND%20a:%22kgraphql%22)
@@ -19,7 +16,7 @@ KGraphQL is available from Maven Central.
Add dependencies:
```kotlin
- implementation("de.stuebingerb:kgraphql:$KGraphQLVersion")
+ implementation("de.stuebingerb:kgraphql:${KGraphQLVersion}")
```
=== "Gradle"
Add Maven Central repository:
@@ -30,7 +27,7 @@ KGraphQL is available from Maven Central.
}
```
- Add dependencies (you can also add other modules that you need):
+ Add dependencies:
```groovy
implementation 'de.stuebingerb:kgraphql:${KGraphQLVersion}'
@@ -57,3 +54,7 @@ KGraphQL is available from Maven Central.
${KGraphQLVersion}
```
+You can also add other artifacts if you need them:
+
+* kgraphql-ktor
+* kgraphql-ktor-stitched
diff --git a/docs/content/Plugins/ktor.md b/docs/content/Plugins/ktor.md
index d40e0f09..df458181 100644
--- a/docs/content/Plugins/ktor.md
+++ b/docs/content/Plugins/ktor.md
@@ -1,13 +1,15 @@
-# Ktor
+# Ktor Plugin
-If you are running a ktor server, there is a separate package that makes it easy to set up a fully functional GraphQL
+If you are running a Ktor server, there is a separate package that makes it easy to set up a fully functional GraphQL
server.
-You first need to add the KGraphQL-ktor package to your dependency
+## Installation
+
+You first need to add the kgraphql-ktor package to your dependencies:
=== "Kotlin Gradle Script"
```kotlin
- implementation("de.stuebingerb:kgraphql-ktor:$KGraphQLVersion")
+ implementation("de.stuebingerb:kgraphql-ktor:${KGraphQLVersion}")
```
=== "Gradle"
```groovy
@@ -22,10 +24,9 @@ You first need to add the KGraphQL-ktor package to your dependency
```
-## Initial setup
+## Initial Setup
-To set up KGraphQL you'll need to install the GraphQL feature like you would any
-other [ktor feature](https://ktor.io/servers/features.html).
+To set up KGraphQL you'll need to install the GraphQL feature like you would any other [Ktor feature](https://ktor.io/servers/features.html).
=== "Example"
```kotlin
@@ -42,15 +43,14 @@ other [ktor feature](https://ktor.io/servers/features.html).
```
Now you have a fully working GraphQL server. We have also set `playground = true`, so when running this you will be able
-to open [http://localhost:8080/graphql](http://localhost:8080/graphql) _(your port number may vary)_ in your browser and
-test it out directly within the browser.
+to open [http://localhost:8080/graphql](http://localhost:8080/graphql) _(your port number may vary)_ in your browser and test it out directly within the browser.
-## Configuration options
+## Configuration Options
The GraphQL feature is extending the standard [KGraphQL configuration](../Reference/configuration.md) and providing its own
set of configuration as described in the table below.
-| Property | Description | Default value |
+| Property | Description | Default Value |
|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|
| endpoint | This specifies what route will be delivering the GraphQL endpoint. When `playground` is enabled, it will use this endpoint also. | `/graphql` |
| context | Allows to add call-specific information to the GraphQL context, see example below. | |
@@ -129,5 +129,5 @@ representation of a GraphQL schema.
}
```
-If schema introspection is enabled, the ktor feature will expose the current schema in Schema Definition
+If schema introspection is enabled, the Ktor feature will expose the current schema in Schema Definition
Language under [http://localhost:8080/graphql?schema](http://localhost:8080/graphql?schema).
diff --git a/docs/content/Reference/Type System/enums.md b/docs/content/Reference/Type System/enums.md
index 943f235c..90630a5e 100644
--- a/docs/content/Reference/Type System/enums.md
+++ b/docs/content/Reference/Type System/enums.md
@@ -1,7 +1,10 @@
# Enums
-GraphQL Enums are a variant on the Scalar type, which represents one of a finite set of possible values. They directly
-map to Kotlin enums:
+GraphQL Enums are a variant on the Scalar type, which represents one of a finite set of possible values.
+
+## Schema
+
+Enums in KGraphQL directly map to Kotlin enums:
=== "Example"
```kotlin
@@ -37,6 +40,8 @@ map to Kotlin enums:
}
```
+## Deprecation
+
Enum values can be [deprecated](../deprecation.md):
=== "Example"
diff --git a/docs/content/Reference/Type System/input-objects.md b/docs/content/Reference/Type System/input-objects.md
index 228d5b83..c44723bf 100644
--- a/docs/content/Reference/Type System/input-objects.md
+++ b/docs/content/Reference/Type System/input-objects.md
@@ -1,7 +1,4 @@
----
-title: Input Objects
-weight: 4
----
+# Input Objects
A GraphQL Input Object defines a set of input fields; the input fields are either scalars, enums, or other input
objects. Like Object and Interface types, Input Object types are inferred from defined operations, but can be explicitly
@@ -145,7 +142,7 @@ This behavior applies recursively to nested types as well. The nested `ChildType
Input Objects are instantiated via their primary constructor. Kotlin default values are used unless a different value
is provided explicitly. Due to a limitation in Kotlin, default values are not visible in the generated schema, though.
-## inputType {}
+## Configuration
Input types can be configured via the `inputType` DSL.
diff --git a/docs/content/Reference/Type System/objects-and-interfaces.md b/docs/content/Reference/Type System/objects-and-interfaces.md
index 105dffe7..834ad18f 100644
--- a/docs/content/Reference/Type System/objects-and-interfaces.md
+++ b/docs/content/Reference/Type System/objects-and-interfaces.md
@@ -1,11 +1,12 @@
-# Overview
+# Objects and Interfaces
GraphQL Objects and Interfaces represent a list of named fields, each of which yield a value of a specific type.
KGraphQL inspects defined operations to create type system, but schema creator is able to explicitly declare and
customize types. Besides, only member properties are inspected.
-**type { }**
-`type` method is entry point to Type DSL.
+## Schema
+
+The `type` method is the entry point to the Type DSL.
See [Extension Properties](#extension-properties), [Kotlin Properties](#kotlin-properties), [Union Properties](#union-properties).
=== "Example"
@@ -70,7 +71,7 @@ and [deprecation](../deprecation.md) of kotlin properties as well as renaming or
}
```
-**KProperty1.ignore**
+## Ignoring Properties
The extension function `ignore()` makes KGraphQL ignore its receiver property.
@@ -98,10 +99,12 @@ The extension function `ignore()` makes KGraphQL ignore its receiver property.
}
```
-**transformation(KProperty1) {}**
+## Property Transformation
The `transformation` function allows to attach data transformation on any existing Kotlin property.
+### Transforming Returned Data
+
=== "Example"
```kotlin
data class Person(val name: String, val age: Int)
@@ -142,6 +145,8 @@ The `transformation` function allows to attach data transformation on any existi
}
```
+### Changing Nullability
+
Transformations can also be used to change the return type of a property, for example to make nullable
properties non-nullable:
@@ -190,6 +195,8 @@ properties non-nullable:
}
```
+### Different Return Type
+
Transformations can even change the type to a completely different class:
=== "Example"
@@ -246,8 +253,6 @@ Transformations can even change the type to a completely different class:
Extension properties allow schema creator to easily attach additional field to any type. It is separately evaluated
after main entity is resolved.
-## property { }
-
`property` method accepts [resolver](../resolver.md) and can be subject of [deprecation](../deprecation.md).
=== "Example"
@@ -296,7 +301,9 @@ members of union type will fail in runtime.
## Data Loaded Properties
-*This feature is still in experimental state.*
+!!! warning ""
+
+ This feature is still in experimental state.
One issue that you could easily encounter when doing a GraphQL API is the N+1 Problem. You can read more about this
problem and solution in depth
diff --git a/docs/content/Reference/Type System/overview.md b/docs/content/Reference/Type System/overview.md
index 4157a5b8..b53a9fd3 100644
--- a/docs/content/Reference/Type System/overview.md
+++ b/docs/content/Reference/Type System/overview.md
@@ -9,7 +9,7 @@ KGraphQL is able to inspect operations and partially infer schema type system, s
explicitly declare every type (but may if needed). Union types and Scalars require explicit definition in Schema DSL.
Inferred classes are interpreted as GraphQL Object or Interface type.
-## Object or Interface?
+## Objects and Interfaces
KGraphQL maps found types (implicit and explicit) to GraphQL simple inheritance model, where every type with fields is
either Object or Interface. Rules are following:
diff --git a/docs/content/Reference/Type System/scalars.md b/docs/content/Reference/Type System/scalars.md
index 5a42fed6..b345d0ff 100644
--- a/docs/content/Reference/Type System/scalars.md
+++ b/docs/content/Reference/Type System/scalars.md
@@ -1,11 +1,10 @@
----
-title: Scalars
-weight: 1
----
+# Scalars
As defined by specification, scalar represents a primitive value in GraphQL. In KGraphQL, besides built-in scalar types,
client code can declare custom scalar types, which can coerce to `String`, `Boolean`, `Int`, `Long`, `Short` or `Float` (`kotlin.Double`).
+## Schema
+
KGraphQL provides a group of DSL methods to define scalars:
* `stringScalar { }`
@@ -36,6 +35,7 @@ correct subtype of `de.stuebingerb.kgraphql.schema.scalar.ScalarCoercion`:
}
}
```
+## Extended Scalars
In addition to the built-in scalars, KGraphQL provides support for `Long`, `Short`, and `Char` which can be added to
a schema using `extendedScalars()`.
diff --git a/docs/content/Reference/Type System/unions.md b/docs/content/Reference/Type System/unions.md
index ba548049..e9690252 100644
--- a/docs/content/Reference/Type System/unions.md
+++ b/docs/content/Reference/Type System/unions.md
@@ -1,39 +1,43 @@
----
-title: Unions
-weight: 3
----
+# Unions
GraphQL Unions represent an object that could be one of a list of GraphQL Object types, but provides for no guaranteed
fields between those types.
-There are 2 ways of defining a union type: manually, and via a sealed class.
+## Schema
-### Manual Configuration
+Sealed classes will automatically result in a union type.
=== "Example"
```kotlin
class MyType
- data class UnionMember1(val one: String)
- data class UnionMember2(val two: String)
+
+ sealed class UnionExample {
+ class UnionMember1(val one: String) : UnionExample()
+ class UnionMember2(val two: String) : UnionExample()
+ }
val schema = KGraphQL.schema {
- val unionExample = unionType("UnionExample"){
- type()
- type()
- }
+ unionType()
- query("myType") {
- resolver { -> MyType() }
+ // Query definition example:
+ query("unionQuery") {
+ resolver { isOne: Boolean ->
+ if (isOne) {
+ UnionExample.UnionMember1(one = "Hello")
+ } else {
+ UnionExample.UnionMember2(two = "World")
+ }
+ }
}
+ // Type property example:
type {
- unionProperty("unionExample") {
- returnType = unionExample
+ property("unionProperty") {
resolver { _, isOne: Boolean ->
if (isOne) {
- UnionMember1(one = "Hello")
+ UnionExample.UnionMember1(one = "Hello")
} else {
- UnionMember2(two = "World")
+ UnionExample.UnionMember2(two = "World")
}
}
}
@@ -43,11 +47,11 @@ There are 2 ways of defining a union type: manually, and via a sealed class.
=== "SDL"
```graphql
type MyType {
- unionExample(isOne: Boolean!): UnionExample!
+ unionProperty(isOne: Boolean!): UnionExample!
}
type Query {
- myType: MyType!
+ unionQuery(isOne: Boolean!): UnionExample!
}
type UnionMember1 {
@@ -61,44 +65,34 @@ There are 2 ways of defining a union type: manually, and via a sealed class.
union UnionExample = UnionMember1 | UnionMember2
```
-(!) Currently there is a limitation on union return types for `query` definitions. This is currently only supported via
-sealed classes. See more information below.
+## Manual Configuration
-### Sealed Class
-
-Sealed classes will automatically result in a union type.
+Unions can also be defined manually as part of a `unionProperty`.
=== "Example"
```kotlin
class MyType
-
- sealed class UnionExample {
- class UnionMember1(val one: String) : UnionExample()
- class UnionMember2(val two: String) : UnionExample()
- }
+ data class UnionMember1(val one: String)
+ data class UnionMember2(val two: String)
val schema = KGraphQL.schema {
- unionType()
+ val unionExample = unionType("UnionExample"){
+ type()
+ type()
+ }
- // Query definition example:
- query("unionQuery") {
- resolver { isOne: Boolean ->
- if (isOne) {
- UnionExample.UnionMember1(one = "Hello")
- } else {
- UnionExample.UnionMember2(two = "World")
- }
- }
+ query("myType") {
+ resolver { -> MyType() }
}
- // Type property example:
type {
- property("unionProperty") {
+ unionProperty("unionExample") {
+ returnType = unionExample
resolver { _, isOne: Boolean ->
if (isOne) {
- UnionExample.UnionMember1(one = "Hello")
+ UnionMember1(one = "Hello")
} else {
- UnionExample.UnionMember2(two = "World")
+ UnionMember2(two = "World")
}
}
}
@@ -108,11 +102,11 @@ Sealed classes will automatically result in a union type.
=== "SDL"
```graphql
type MyType {
- unionProperty(isOne: Boolean!): UnionExample!
+ unionExample(isOne: Boolean!): UnionExample!
}
type Query {
- unionQuery(isOne: Boolean!): UnionExample!
+ myType: MyType!
}
type UnionMember1 {
@@ -125,3 +119,8 @@ Sealed classes will automatically result in a union type.
union UnionExample = UnionMember1 | UnionMember2
```
+
+!!! note
+
+ Currently there is a limitation on union return types for `query` definitions. This is currently only supported via
+ sealed classes, see above.
diff --git a/docs/content/Reference/configuration.md b/docs/content/Reference/configuration.md
index 09b85b31..b110d8a3 100644
--- a/docs/content/Reference/configuration.md
+++ b/docs/content/Reference/configuration.md
@@ -1,6 +1,8 @@
+# Configuration
+
KGraphQL schema allows configuration of the following properties:
-| Property | Description | Default value |
+| Property | Description | Default Value |
|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| useDefaultPrettyPrinter | Schema pretty prints JSON responses | `false` |
| useCachingDocumentParser | Schema caches parsed query documents | `true` |
diff --git a/docs/content/Reference/deprecation.md b/docs/content/Reference/deprecation.md
index 4a794d44..b57d621c 100644
--- a/docs/content/Reference/deprecation.md
+++ b/docs/content/Reference/deprecation.md
@@ -1,6 +1,4 @@
----
-title: Deprecation
----
+# Deprecation
Schema creators are able to deprecate fields, operations, enum values, and input values. DSL builders for those schema
elements expose method `deprecate(reason: String)`. Deprecation is visible in schema introspection system with fields
diff --git a/docs/content/Reference/errorHandling.md b/docs/content/Reference/errorHandling.md
index 5cba61c9..d3e5c4d3 100644
--- a/docs/content/Reference/errorHandling.md
+++ b/docs/content/Reference/errorHandling.md
@@ -259,4 +259,6 @@ to the standard implementation, completely replaced, or a mixture of both.
}
```
-(!) Exceptions from the error handler itself are *not* wrapped, regardless of the `wrapErrors` configuration.
+!!! note
+
+ Exceptions from the error handler itself are *not* wrapped, regardless of the `wrapErrors` configuration.
diff --git a/docs/content/Reference/operations.md b/docs/content/Reference/operations.md
index 3c23509c..04104255 100644
--- a/docs/content/Reference/operations.md
+++ b/docs/content/Reference/operations.md
@@ -1,7 +1,5 @@
# Operations
-## Overview
-
There are three types of operations that GraphQL models:
* [Query](#query) – a read‐only fetch.
@@ -10,9 +8,11 @@ There are three types of operations that GraphQL models:
Each operation is represented by an operation name and a selection set.
+## Schema
+
In KGraphQL, operation is declared in `SchemaBuilder` block. Every operation has 2 properties:
-| name | description |
+| Name | Description |
|----------|-------------------------|
| name | name of operation |
| resolver | [Resolver](resolver.md) |
@@ -23,7 +23,7 @@ Operations can be [deprecated](deprecation.md)
Subscriptions are not supported yet.
-### Query
+## Query
`query` allows to create a resolver for a query operation.
@@ -40,7 +40,7 @@ Subscriptions are not supported yet.
This example adds query with name hero, which returns new instance of R2-D2 Hero. It can be queried with selection set
for name or age, example query: `{hero{name, age}}`
-### Mutation
+## Mutation
`mutation` allows to create a resolver for a mutation operation.
@@ -54,6 +54,6 @@ for name or age, example query: `{hero{name, age}}`
This example adds mutation with name `createHero`, which returns passed name.
-### Subscription
+## Subscription
`subscription` operations are not supported yet.
diff --git a/docs/content/Reference/resolver.md b/docs/content/Reference/resolver.md
index ca8021d2..46ec1097 100644
--- a/docs/content/Reference/resolver.md
+++ b/docs/content/Reference/resolver.md
@@ -1,11 +1,11 @@
# Resolver
-## Basics
-
In GraphQL every property needs a resolver. The resolver is the piece of system logic, required to resolve the response
graph. [Operations](operations.md), [Extension Properties](Type%20System/objects-and-interfaces.md/#extension-properties) and [Union Properties](Type%20System/unions.md) accept resolver, which allows
schema creators to configure schema behaviour.
+## Schema
+
Resolver clause accepts kotlin function and returns its DSL item, which is entry point for additional customization of
resolver:
@@ -18,10 +18,7 @@ resolver:
## Arguments
-`withArgs` closure exposes single method `arg`
-
-**arg { }**
-`arg` exposes the possibility to customize argument default values. The default value is automatically used if query doesn't
+The `withArgs` closure has a method `arg` that exposes the possibility to customize argument default values. The default value is automatically used if query doesn't
provide any, and is matched by argument name.
=== "Example"
@@ -72,3 +69,75 @@ Then in your query execution process you will provide a `Context` like shown her
}
schema.execute(query, variables, ctx)
```
+
+## Node
+
+Similar to `Context`, resolvers can also request for the `Node` object, which is a representation of the current node
+in the response graph.
+
+=== "Example"
+ ```kotlin
+ data class Director(val firstName: String, val lastName: String)
+ data class Film(val title: String, val director: Director)
+
+ val schema = KGraphQL.schema {
+ configure { useDefaultPrettyPrinter = true }
+
+ query("films") {
+ resolver { ->
+ listOf(
+ Film("Prestige", Director("Christopher", "Nolan")),
+ Film("Se7en", Director("David", "Fincher"))
+ )
+ }
+ }
+ type {
+ property("fullPath") {
+ resolver { _: Film, node: Execution.Node -> node.fullPath.joinToString(".") }
+ }
+ }
+ type {
+ property("fullPath") {
+ resolver { _: Director, node: Execution.Node -> node.fullPath.joinToString(".") }
+ }
+ }
+ }
+ ```
+=== "Query"
+ ```graphql
+ query {
+ films {
+ title
+ fullPath
+ director {
+ firstName
+ lastName
+ fullPath
+ }
+ }
+ }
+ ```
+=== "Response"
+ ```json
+ {
+ "data" : {
+ "films" : [ {
+ "title" : "Prestige",
+ "fullPath" : "films.0.fullPath",
+ "director" : {
+ "firstName" : "Christopher",
+ "lastName" : "Nolan",
+ "fullPath" : "films.0.director.fullPath"
+ }
+ }, {
+ "title" : "Se7en",
+ "fullPath" : "films.1.fullPath",
+ "director" : {
+ "firstName" : "David",
+ "lastName" : "Fincher",
+ "fullPath" : "films.1.director.fullPath"
+ }
+ } ]
+ }
+ }
+ ```
diff --git a/docs/content/Reference/stitching.md b/docs/content/Reference/stitching.md
index 656108cb..15f037f9 100644
--- a/docs/content/Reference/stitching.md
+++ b/docs/content/Reference/stitching.md
@@ -1,8 +1,8 @@
# Schema Stitching
-*This feature is still in experimental state.*
+!!! warning ""
-## Overview
+ This feature is still in experimental state.
Schema stitching is a method to take multiple GraphQL schemas and combine them into a single, unified schema. This can
be useful when implementing an integration layer for a frontend that orchestrates multiple backend APIs to provide your
@@ -11,6 +11,31 @@ UI with all the required data in a single request, without having to think about
By linking properties to remote queries, one can also enhance individual schemas by e.g. automatically resolving
identifiers.
+## Installation
+
+Schema stitching requires adding the kgraphql-ktor-stitched package to your dependencies:
+
+=== "Kotlin Gradle Script"
+ ```kotlin
+ implementation("de.stuebingerb:kgraphql-ktor-stitched:${KGraphQLVersion}")
+ ```
+=== "Gradle"
+ ```groovy
+ implementation 'de.stuebingerb:kgraphql-ktor-stitched:${KGraphQLVersion}'
+ ```
+=== "Maven"
+ ```xml
+
+ de.stuebingerb
+ kgraphql-ktor-stitched
+ ${KGraphQLVersion}
+
+ ```
+
+Because remote schemas require executing HTTP requests, schema stitching is (currently) only supported in combination with kgraphql-ktor.
+
+## Schema
+
In KGraphQL, schema stitching is configured via the `stitchedSchema` DSL. Each stitched schema has 1-n *remote* schemas,
and up to one *local* schema.
@@ -34,7 +59,7 @@ and up to one *local* schema.
}
```
-### Remote Schema Fetching
+## Remote Schema Fetching
Remote schemas are usually fetched via introspection query.
@@ -55,13 +80,13 @@ Remote schemas are usually fetched via introspection query.
}
```
-### Duplicate Types
+## Duplicate Types
Currently, if multiple schemas define types with the same name, the local type wins. For identical types from remote
schemas there is no guaranteed order of precedence. Future versions may provide better tools to deal with such
situations.
-### Remote Execution
+## Remote Execution
To execute remote queries, consumers need to provide a `RemoteRequestExecutor` that receives an `Execution.Remote` node
and the current `Context`, and has to return the result as `JsonNode?`:
@@ -76,7 +101,7 @@ interface RemoteRequestExecutor {
To simplify implementation, consumers can extend the `AbstractRemoteRequestExecutor` and only provide the implementation
for actually executing the HTTP request itself.
-### Fragments
+## Fragments
Fragments based on remote types work but cannot use Kotlin's type system to determine the correct condition type.
Therefore, queries including fragments must also request the `__typename`. Future implementation might automatically
@@ -97,7 +122,7 @@ include this.
}
```
-### Local "Remote" Execution
+## Local "Remote" Execution
Due to current implementation details, properties stitched to a *local* query will also be handled by the
`RemoteRequestExecutor`, and therefore the schema has to provide a `localUrl`. Future implementation will likely support
@@ -112,7 +137,7 @@ actual local execution.
}
```
-### Linking Properties
+## Linking Properties
All (local and remote) types of a schema can be extended via stitched properties that are translated into remote query
calls during execution. The following example adds two fields to the `Type1` type:
@@ -139,4 +164,7 @@ calls during execution. The following example adds two fields to the `Type1` typ
Stitched properties are nullable by default, and if a parent property is `null`, the remote execution is skipped and
results in a value of `null` for the stitched property itself.
+If a stitched property uses a `parentFieldName`, then this field must also be requested by the initial query. Future
+implementation might automatically include this.
+
See `StitchedSchemaExecutionTest.kt` for an extensive list of different examples.
diff --git a/docs/content/Tutorials/ktor.md b/docs/content/Tutorials/ktor.md
index c14a7dc0..07e5515f 100644
--- a/docs/content/Tutorials/ktor.md
+++ b/docs/content/Tutorials/ktor.md
@@ -1,36 +1,40 @@
-# Fully functional GraphQL & Ktor server
+# Ktor Tutorial
-We will be using the [ktor intellij plugin](https://plugins.jetbrains.com/plugin/10823-ktor) to get setup.
+We will be using the [Ktor intellij plugin](https://plugins.jetbrains.com/plugin/10823-ktor) to setup a fully functional GraphQL & Ktor server.
-The very first thing we'll be doing is creating a new IntelliJ project and use the ktor template.
+## Project Setup
+
+The very first thing we'll be doing is creating a new IntelliJ project and use the Ktor template.

After this we'll press "Next" and fill out the necessary information and then press "Finish". Now we have a brand new
-ktor project.
+Ktor project.
-Now we can begin adding the needed dependencies.
+## Dependencies
-Replace `x.x.x` with the latest
-version [](https://search.maven.org/search?q=g:%22de.stuebingerb%22%20AND%20a:%22kgraphql%22).
+Now we can begin adding the needed dependencies.
=== "Kotlin Gradle Script"
```kotlin
dependencies {
- implementation("de.stuebingerb:kgraphql:x.x.x")
- implementation("de.stuebingerb:kgraphql-ktor:x.x.x")
+ implementation("de.stuebingerb:kgraphql:${KGraphQLVersion}")
+ implementation("de.stuebingerb:kgraphql-ktor:${KGraphQLVersion}")
}
```
=== "Gradle"
```groovy
dependencies {
- implementation "de.stuebingerb:kgraphql:x.x.x"
- implementation "de.stuebingerb:kgraphql-ktor:x.x.x"
+ implementation "de.stuebingerb:kgraphql:${KGraphQLVersion}"
+ implementation "de.stuebingerb:kgraphql-ktor:${KGraphQLVersion}"
}
```
-The only thing left is installing the GraphQL feature onto our server by opening `src/Application.kt` and use these
-lines as the `Application.module` function
+
+## GraphQL Feature
+
+The only thing left is installing the GraphQL feature onto our server by opening `src/Application.kt` and use the following
+lines as the `Application.module` function.
=== "Application.kt"
```kotlin
@@ -50,8 +54,10 @@ lines as the `Application.module` function
Now we have a fully functional GraphQL Server and we can startup our server by pressing the green play icon beside the
`main` function.
+## Validating the Setup
+
We can test out our server by going to [localhost:8080/graphql](http://localhost:8080/graphql) and our `hello` query
-should work by providing this query to the GraphQL Playground
+should work by providing this query to the GraphQL Playground.

diff --git a/docs/content/Tutorials/starwars.md b/docs/content/Tutorials/starwars.md
index 1abea9b1..53443c71 100644
--- a/docs/content/Tutorials/starwars.md
+++ b/docs/content/Tutorials/starwars.md
@@ -1,10 +1,10 @@
----
-title: Star Wars Tutorial
-weight: 1
----
+# Star Wars Tutorial
-As example, let's partially reproduce part of Star Wars schema from official GraphQL tutorial. First, we need to define
-our domain model, by plain kotlin classes:
+As example, let's partially reproduce part of Star Wars schema from official GraphQL tutorial.
+
+## Domain Model
+
+First, we need to define our domain model as plain kotlin classes:
=== "Example"
```kotlin
@@ -37,7 +37,9 @@ our domain model, by plain kotlin classes:
) : Character
```
-Next, we define our data
+## Data
+
+Next, we define our data:
=== "Example"
```kotlin
@@ -46,6 +48,8 @@ Next, we define our data
val r2d2 = Droid("2001", "R2-D2", emptyList(), Episode.values().toSet(), "Astromech")
```
+## Schema
+
Then, we can create the schema:
=== "Example"
@@ -81,6 +85,8 @@ Then, we can create the schema:
}
```
+## Queries
+
Now, we can query our schema:
=== "Example"
diff --git a/docs/content/assets/replace_maven_version.js b/docs/content/assets/replace_maven_version.js
new file mode 100644
index 00000000..d640a7a4
--- /dev/null
+++ b/docs/content/assets/replace_maven_version.js
@@ -0,0 +1,21 @@
+/**
+ * Replaces all occurrences of ${KGraphQLVersion} in the HTML with the latest version tag provided by Material for MkDocs
+ * in the .md-source__fact--version element.
+ */
+document$.subscribe(function () {
+ let toReplace = '${KGraphQLVersion}';
+ let latest_tag = document.querySelector("li.md-source__fact--version")?.textContent;
+ if (latest_tag != null) {
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
+ acceptNode: function (node) {
+ return node.textContent.includes(toReplace)
+ ? NodeFilter.FILTER_ACCEPT
+ : NodeFilter.FILTER_REJECT;
+ }
+ });
+ let node;
+ while ((node = walker.nextNode()) !== null) {
+ node.nodeValue = node.nodeValue.replaceAll(toReplace, latest_tag);
+ }
+ }
+})
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index a4348744..b6278c17 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -41,6 +41,7 @@ extra_css:
extra_javascript:
- assets/hljs/highlight.min.js # Download from https://highlightjs.org/download/
- assets/hljs/init.js
+ - assets/replace_maven_version.js
plugins:
- search
@@ -49,6 +50,7 @@ plugins:
- "**/include-*.md"
markdown_extensions:
+ - admonition
- pymdownx.smartsymbols
- pymdownx.superfences
- pymdownx.highlight:
@@ -62,26 +64,25 @@ extra:
link: https://github.com/stuebingerb/KGraphQL
nav:
- - 'Overview': 'index.md'
- - 'Installation': 'Installation/index.md'
- - 'Examples': 'Examples/index.md'
- - 'Plugins':
- - 'Ktor': 'Plugins/ktor.md'
+ - 'index.md'
+ - 'Installation/index.md'
+ - 'Examples/index.md'
+ - 'Plugins/ktor.md'
- 'Tutorials':
- - 'Star Wars Tutorial': 'Tutorials/starwars.md'
- - 'Ktor Tutorial': 'Tutorials/ktor.md'
+ - 'Tutorials/ktor.md'
+ - 'Tutorials/starwars.md'
- 'Reference':
- - 'Operations': 'Reference/operations.md'
- - 'Configuration': 'Reference/configuration.md'
- - 'Resolver': 'Reference/resolver.md'
- - 'Error Handling': 'Reference/errorHandling.md'
- - 'Deprecation': 'Reference/deprecation.md'
- - 'Access Rule': 'Reference/accessRule.md'
+ - 'Reference/operations.md'
+ - 'Reference/configuration.md'
+ - 'Reference/resolver.md'
+ - 'Reference/errorHandling.md'
+ - 'Reference/deprecation.md'
+ - 'Reference/accessRule.md'
- 'Type System':
- - 'Overview': 'Reference/Type System/overview.md'
- - 'Scalars': 'Reference/Type System/scalars.md'
- - 'Enums': 'Reference/Type System/enums.md'
- - 'Unions': 'Reference/Type System/unions.md'
- - 'Input Objects': 'Reference/Type System/input-objects.md'
- - 'Objects and Interfaces': 'Reference/Type System/objects-and-interfaces.md'
- - 'Stitching': 'Reference/stitching.md'
+ - 'Reference/Type System/overview.md'
+ - 'Reference/Type System/scalars.md'
+ - 'Reference/Type System/enums.md'
+ - 'Reference/Type System/unions.md'
+ - 'Reference/Type System/input-objects.md'
+ - 'Reference/Type System/objects-and-interfaces.md'
+ - 'Reference/stitching.md'