Skip to content

tgirard12/graphql-kotlin-dsl

Repository files navigation

graphql-kotlin-dsl

download

Kotlin DSL to generate GraphQL Instance and Schema IDL for https://github.com/graphql-java/graphql-java

  • Use a Kotlin DSL to configure your schema :

    • query, mutation, type, enum

    • Add/remove field on any kotlin Class

    • Add descriptions

  • Add DataFetchers inside your DSL for :

    • query, mutation

    • Fields inside a type

  • Or just use extensions for graphql-java library

Download

compile 'com.tgirard12:graphql-kotlin-dsl:VERSION'

Sample

data class User(
    val name: String,
    val email: String,
    val deleteField: Int
)

enum class Right {
    read, write, execute
}

schemaDsl {
    // Scalar
    scalar<Double> { GqlJavaScalars.double }
    scalar<UUID> { GqlJavaScalars.uuid }

    // Types and Enums
    type<User>(typeDescription = "An User") {
        desc("email", "User Email")

        addField<String>(name = "otherName") {
            asyncDataFetcher<String>("otherName") {
                "MyOtherName"
            }
        }

        addField<Right> {
            description = "User Right"
            nullable = true
            asyncDataFetcher<Right>("right") {
                Right.execute
            }
        }

        dropField("deleteField")
    }
    enum<Right>(enumDescription = "An enum") { }

    // Queries
    query<User>(queryDescription = "User By Id") {
        arg<UUID> { name = "id" }

        asyncDataFetcher { env ->
            Stubs.users.firstOrNull { it.id == env.arguments["id"] }
        }
    }
    query<Unit> {
        name = "users"
        description = "All Users"
        returnType = "[User]"

        staticDataFetcher {
            Stubs.users
        }
    }

    // Mutations
    mutation<User>(mutationDescription = "Update a user") {
        name = "updateUser"

        arg<Int> {
            name = "count"
            nullable = true
        }
        arg<String> { name = "name" }

        asyncDataFetcher { env ->
            User(UUID.randomUUID(), env.arguments["name"] as String, "[email protected]", 5)
        }
    }
}.graphQL {
     queryExecutionStrategy(AsyncExecutionStrategy())

}.execute("""
    query user {
       user(id: "b6214ea0-fc5a-493c-91ea-939e17b2e95f") {
           id
           email
           name
           otherName
           right
       }
    }""")

How that work

1. Generate this GraphQl String schema :

schema {
    query: QueryType
    mutation: MutationType
}

type QueryType {
    # User By Id
    user(id: UUID!): User!
    # All Users
    users: [User]!
}

type MutationType {
    # Update a user
    updateUser(count: Int, name: String!): User!
}

scalar Double
scalar UUID

# An enum
enum Right {
    read
    write
    execute
}

# An User
type User {
    # User Email
    email: String!
    id: UUID!
    name: String!

    otherName: String!
    # User Right
    right: Right
}

2. Use the DataFetcher from the DSL to generate RuntimeWiring :

  • Load the String schema with SchemaParser.parse() and SchemaGenerator.makeExecutableSchema()

  • Create RuntimeWiring with dataFetcher { …​ } DSL

3. Configure GraphQl.Builder()

  • Use the DSL to configure GraphQl.Builder()

graphql-java Extension functions and DSL

GraphQL and RuntimeWiring DSL

schemaDsl {
  ...
}.graphQL({ // Define RuntimeWiring.Builder

  scalarUUID()
  scalarDouble()

  queryType {
    staticDataFetcher<List<User>>("users") { users }
    asyncDataFetcher<User>("user") { e ->
      e.arguments["id"]?.let { id ->
        users.firstOrNull {
          id == it.id
        }
      }
    }
  }
  mutationType {
    asyncDataFetcher("updateUser") { e ->
      User(id = UUID.fromString("773b29ba-6b2b-49fe-8cb1-36134689c458"),
        name = e.arguments["name"] as String? ?: "",
        email = e.arguments["email"] as String)
    }
  }
  type<SimpleTypes> {
    asyncDataFetcher<User>("user") { users[0] } // Custom fetcher for SimpleTypes.user
  }
}, { GraphQL.Builder
  queryExecutionStrategy(AsyncExecutionStrategy())
})

GraphQLSchema instance

schemaDsl {
  ...
}.graphQLSchema(myRuntimeWiring)

Scalar DSL

val scalar = scalarTypeDsl<LocalDateTime> {
  serialize {
    // ...
  }
  parseValue {
    // ...
  }
  parseLiteral {
    // ...
  }
}

Custom scalars : GqlJavaScalars.uuid, GqlJavaScalars.double